home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Belgian Amiga Club - ADF Collection
/
BS1 part 41.zip
/
BS1 part 41
/
Abacus diskdrives IO.adf
/
Assembler
/
DeepCopy.s
< prev
next >
Wrap
Text File
|
1978-06-28
|
130KB
|
4,289 lines
;The Listing of the Copy Program
key = $BFEC01
Cont = $BFEE01
IntCon = $BFED01
MaxWait = $4000
MinWait = $1000
;
;------- graphics.library ------
;
Textout = -30 - 30
InitRastPort = -30 -168
Movee = -30 -210
Draw = -30 -216
RectFill = -30 -276
SetAPen = -30 -312
InitBitMap = -30 -360
;
;--------- exec.library --------
;
ExecBase = 4
;
AllocMem = -30 -168
AvailMem = -216
FreeMem = -30 -180
OldOpenLibrary = -30 -378
CloseLibrary = -30 -384
FindName = -276
;
MEMF_Chip = $02
MEMF_Fast = $04
MEMF_Largest = $20000
DevList = 350
Port = 36 ;Drive 0
IDNestCnt = 294
;
;-------------------------------
;
floppy_size = floppyend - floppy
floppy_s = floppy_size/6-1
ON = 1
OFF = 0
;Error-Flag Values
NoError = $0000
NoSync = $0001
LengthUnequal = $0002
LengthUnequal2 = $0003
NoDisk = $0004
ReadError = $0005
VerifyError = $0006
DiskProtect = $0007
NotProtect = $0008
Escape = $0009
CopyAttempt1 = 3 ;Attempts on illegal Data
CopyAttempt2 = 3 ;Attempts on NoSync
;Load options
WithoutSync = $0000
WithSync = $ffff
;Write options
NoIndex = $0000
IndexOk = $ffff
;Size of memory used
SortBlockNum = $40 ;Number of blocks,
;whose length is sorted
Bytesread = $3600
BSize = 2*Bytesread
req = 2 ;Chip-Memory
CIAA = $BFE000
GapLengthF = $500 ;Length of Gap for FastCopy
NumReadsF = 5 ;Number of Read attempts for Readerror (Fast)
;Values for Cruncher
ShrtNull = $80
MiddleNull = $20
LongNull = $08
ShrtNorm = $40
MiddleNorm = $10
LongNorm = $04
ShrtNone = $c0
MiddleNone = $30
LongNone = $02
EmptyBlock = $01
lea DevName,a1
move.l $4,a6
lea DevList(a6),a0
jsr FindName(a6)
move.l d0,a0
beq Ende
lea Port(a0),a0
clr.w d0
\An2: tst.l (a0)+
beq \An1
bset d0,Drives
\An1: addq.w #1,d0
cmp.w #4,d0
bne.s \An2
move.l ExecBase,a6
lea gfxname,a1
jsr OldOpenLibrary(a6)
move.l d0,gfxbase
beq no_gfxbase
move.l #$2800,d0
move.l #$10002,d1
jsr AllocMem(a6)
move.l d0,bit_adress
beq no_bitmap
move.l #copsize+2,d0
move.l #$10002,d1
jsr AllocMem(a6)
move.l d0,cop_adress
beq no_copper
MOVE.L #BSize,D0
MOVE.L #req,D1
JSR AllocMem(A6)
TST.L D0
BEQ no_DPuffer
MOVE.L D0,TrackBuffer1
addq.l #6,TrackBuffer1
add.l #Bytesread-6,d0
move.l D0,TrackBuffer2
bsr GetMemory ;Memory for Cruncher
bra beg
copy_start: MOVE.L $4,A6
MOVE.B #$FF,$BFD300
move.w #$0020,$dff09a
JSR Disable
MOVE.W #$8210,$DF096 ;set DMA-Reg.
clr.w FreeFlagCh
clr.w FreeFlagFa
bsr HeadMov ;set Heads to Null and set Motorbits
bsr Start_End ;determine copy area
cmp.b #ON,dc1 ;Deepcopy 1
beq \ME7
cmp.b #ON,dc2
bne \ME5
\ME7: move.b SD,d0 ;one Drive-Copy?
cmp.b DD,d0
beq \ME6 ;yes
bsr SwitchS
\ME5: bsr TestProtect
tst.l d0
bmi \ME4
bsr protect_source
tst.l d0
bmi \ME3 ;Escape
bra \ME5
\ME4:
cmp.b #ON,fa ;Fastcopy on?
bne \ME1
bsr FastCopy
bra \ME3
\ME1: cmp.b #ON,dc1 ;Deepcopy1 on?
bne \ME2
bsr DeepCopy
bra \ME3
\ME2: cmp.b #ON,dc2 ;Deepcopy2 on?
bne \ME3
\ME6: bsr DeepCopy
\ME3:
bsr SwitchS
bsr MotorOff
bsr SwitchD
bsr MotorOff
move.w #$0600,$dff09e
move.w #$8100,$dff09e ;restore Bits
\Error: bsr Enable
move.w #$8020,$dff09a
Ende: rts
TextoutL: move.w StartTrack,d0
lsr.w #1,d0
move.b d0,Cylinder
bsr reading_cyl
rts
TextoutS: move.w StartTrack,d0
lsr.w #1,d0
move.b d0,Cylinder
bsr writing_cyl
rts
;output Read-Error
RError: move.w StartTrack,d0
move.b #1,side
btst #0,d0
bne \RE1
clr.b side
\RE1: lsr.w #1,d0
move.b d0,Cylinder
bsr read_error
rts
;output Write-Error
WError: move.w StartTrack,d0
move.b #1,side
btst #0,d0
bne \RE1
clr.b side
\RE1: lsr.w #1,d0
move.b d0,Cylinder
bsr write_error
rts
FastCopy:
bsr GapCreate
move.b DD,d0
cmp.b SD,d0
beq \FC1
bra FastCopyML ;for several Drives
\FC1: bra FastCopyEL ;for one Drive
;FastCopy for several Drives
FastCopyML:
bsr SwitchD
\FC5: bsr TestProtect
tst.l d0
bpl \FC1
bsr protect_Destination
tst.l d0
bmi \Error ;Escape
bra \FC5
\FC1: bsr TextoutL
bsr TrackLSF ;load Track from Source
cmp.w #NoDisk,ErrorFlag
beq \Error
bsr SwitchD
move.w StartTrack,d0
bsr HeadPos
bsr TextoutS
bsr TrackFastWrite
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #DiskProtect,ErrorFlag
bne \FC3
bsr protect_destination
bra \Error
\FC3: cmp.b #ON,vd ;Verify ON ?
bne \FC2 ;branch if not on
bsr TrackFVerify
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #VerifyError,ErrorFlag
bne \FC2
bsr WError
bsr compare_drives
\FC2: add.w #1,StartTrack
move.w StartTrack,d0
cmp.w EndTrack,d0
bls \FC1
\Error rts
;FastCopy for one Drive
FastCopyEL:
clr.b ShrtByte ;ShortByte for Chruncher = 0
move.w #$1600,Length
bsr NextMemory ;assign memory
\FCEL1: bsr TestProtect
tst.l d0
bmi \FCEL3
bsr protect_Source
tst.l d0
bmi \FCEL2 ;Escape activated
bra \FCEL1
\FCEL3: bsr FCopy1DL ;read in memory
tst.l d0
bmi \FCEL2
move.l WriteAddrs,a5
add.l #GapLengthF,a5
\FCEL7: move.w TNumBufferA,StartTrack
bsr insert_destination
tst.l d0
bmi \FCEL2 ;Escape
\FCEL5: bsr TestProtect
tst.l d0
bpl \FCEL6
bsr protect_Destination
tst.l d0
bmi \FCEL2 ;Escape activated
bra \FCEL5
\FCEL6: bsr FCopy1DS ;Write Tracks
tst.l d0
bmi \FCEL2
cmp.b #ON,ws ;write repeatedly ?
bne \FCEL8 ;no
bsr write_b_again
cmp.w #Escape,ErrorFlag
beq \FCEL2
tst.l d0
bpl \FCEL7 ; write again
\FCEL8: move.w StartTrack,TNumBufferA
move.w TNumBufferE,d0
cmp.w EndTrack,d0
bcc \FCEL2
bsr insert_source
tst.l d0
bmi \FCEL2 ;Escape
bra \FCEL1
\FCEL2: rts
FCopy1DL:
\FCD1: bsr TrackLSF ;load Track from Source
cmp.w #NoDisk,ErrorFlag
beq \Error
move.l TrackBuffer2,a0 ;pass Pointer
bsr Packe ;crunch Track
tst.l d0
bmi \FCD2 ;memory full
bsr TextoutL ;output Text
add.w #1,StartTrack
move.w StartTrack,d0
cmp.w EndTrack,d0
bls \FCD1
\FCD2: subq.w #1,StartTrack
clr.l d0
move.w StartTrack,TNumBufferE ;Last Track
rts
\Error: move.l #-1,d0
rts
;Copy portion for writing with one Drive
FCopy1DS:
move.w StartTrack,d0 ;first Track read
\FDS1: bsr HeadPos
bsr TextoutS
move.l TrackBuffer2,a0 ;Buffer for Track (Target)
bsr EntPacke ;Track in regular size again
move.l a5,a1 ;Target (TrackBuffer1 + Gap)
move.l TrackBuffer2,a0 ;Source
move.w StartTrack,d0 ;Track to be read
bsr CodeTrack ;code Track
move.w #00,FirstBlockSp ;first Block = Null
bsr TrackFastWrite
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #DiskProtect,ErrorFlag
bne \FDS3
bsr protect_destination
bra \Error
\FDS3: cmp.b #ON,vd ;Verify ON ?
bne \FDS2 ;branch if not on
bsr TrackFVerify
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #VerifyError,ErrorFlag
bne \FDS2
bsr WError
\FDS2: bsr Get_Key ;Escape activated?
cmp.b #$45,d0
bne \FCS4 ;no, continue
move.w #Escape,ErrorFlag
bra \Error
\FCS4: addq.w #1,StartTrack
move.w StartTrack,d0
cmp.w TNumBufferE,d0
bls \FDS1
clr.l d0
clr.w FreeFlagCh ;Chip-Mem is available again
clr.w FreeFlagFa ;Fast-Memomory is available again
rts
\Error: move.l #-1,d0
rts
;crunch Track and store
;>= A0 Pointer to TrackBuffer
Packe: ;Pointer to Track
move.l a2,-(a7)
move.l a0,a2
\PA2: lea TrackPointer,a0 ;Pointer to Track-Table
clr.l d0
move.w StartTrack,d0 ;Track-Number
lsl.w #2,d0
adda.l d0,a0 ;Pointer to Memory pointer
move.l MemoryBeg,(a0) ;store Pointer to Track
move.l MemoryBeg,a1
move.l a2,a0
bsr Crunch
tst.l d0
bpl \PA1 ;Ok, continue
bsr NextMemory ;get new Mempory
tst.l d0
bpl \PA2 ;Ok, Memory obtained
\PA1: move.l (a7)+,a2
rts
;get Track from memory
;>= A0 = Pointer to Target for Track
EntPacke:
move.l a0,a1
lea TrackPointer,a0 ;Pointer to Track-Table
clr.l d0
move.w StartTrack,d0 ;Track-Number
lsl.w #2,d0
adda.l d0,a0 ;Pointer to memory pointer
move.l (a0),a0 ;get Pointer to Track
bsr DeCrunch
rts
GetMemory:
move.l a6,-(a7)
move.l #MEMF_Chip,d1
or.l #MEMF_Largest,d1
move.l ExecBase,a6
jsr AvailMem(a6)
move.l d0,LengthChip
bne \HS1
clr.l MemoryChip ;no Chip available
bra \HS2 ;get Fast-Memory
\HS1: jsr AllocMem(a6)
move.l d0,MemoryChip
\HS2: move.l #MEMF_Fast,d1
or.l #MEMF_Largest,d1
jsr AvailMem(a6)
move.l d0,LenghtFast
bne \HS3 ;ok
clr.l MemoryFast
bra \HS4 ;no fast memory available
\HS3: jsr AllocMem(a6)
move.l d0,MemoryFast
\HS4: move.l (a7)+,a6
clr.w FreeFlagCh ;memory is free
clr.w FreeFlagFa
rts
;get next memory block
NextMemory:
tst.w FreeFlagCh ;Chip not available
bpl \NS1 ;Yes, is free
\NS3: tst.w FreeFlagFa ;Fast memory still available
bpl \NS4 ;Yes, is free
\NS5: move.l #-1,d0 ;no memory free
bra \NS2
\NS4: move.l MemoryFast,d0
beq \NS5 ;no Fast memory free
move.l LenghtFast,d1
move.w #$ffff,FreeFlagFa ;Fast memory occupied
bra \NS6
\NS1: move.l MemoryChip,d0
beq \NS3 ;no Chip free
move.l LengthChip,d1
move.w #$ffff,FreeFlagCh ;occupy Chip
\NS6: move.l d0,MemoryBeg
move.l d1,MemoryLength
clr.l d0
\NS2: rts
;load Track (Fastcopy)
;>= StartTrack = Track to be loaded
;=> SBytes = Number of Bytes to be written
;=> WriteAddrs = Address from which writing starts
TrackLSF:
movem.l d2/a2,-(a7)
bsr SwitchS
move.l TrackBuffer1,a5
move.l a5,WriteAddrs
add.l #GapLengthF,a5
move.l TrackBuffer2,a4
move.w #(GapLengthF+$2ec0+2),SLength
move.w StartTrack,d0
bsr HeadPos
move.w #NumReadsF-1,d2
\TSF6: bsr FastReads
move.w FirstBlock,FirstBlockSp ;1. Block loaded
cmp.w #NoDisk,ErrorFlag
beq \TSF7
cmp.w #ReadError,ErrorFlag
bne \TSF5
dbf d2,\TSF6 ;branch, if reading again
tst.l d0 ;No Sync found
bpl \TSF1
move.l a4,a0 ;pass Buffer
bsr DOSClear ;store Track empty
\TSF1:
bsr RError ;output error
move.l a4,a0
move.l a5,a1
move.w StartTrack,d0 ;pass Track-Number
bsr CodeTrack ;generate Track from data
clr.w FirstBlockSp ;first Block = 0
\TSF5: clr.l d0
\TSF7: movem.l (a7)+,d2/a2
rts
;enter Gap Bytes in Track-Buffer
GapCreate:
move.l TrackBuffer1,a0
move.w #(GapLengthF/4)+4,d0
\LS1: move.l #$aaaaaaaa,(a0)+
dbf d0,\LS1
rts
TrackFVerify:
movem.l d2-d4/a4-a5,-(a7)
clr.w d3 ;Dest.-Counter
clr.w VerErrFlag ;erase Verify-Error-Flag
move.b MotorBits,d4 ;store Motor Bits
\TF2: move.l TrackBuffer2,a5
move.l TrackBuffer1,a4
add.l #GapLengthF,a4
\TF1:
move.b tr,d2 ;number of Write attempts
move.w d3,d1 ;Dest.-Number to D1
bsr SwitchND ;switch on Destination
tst.l d0 ;Drive present
bmi \TF6 ;No
\TF4: bsr FastVerify
cmp.w #NoDisk,ErrorFlag
beq \TF3 ;Error, No Disk
cmp.w #VerifyError,ErrorFlag
bne \TF6 ;no Error, continue
subq.b #1,d2 ;decrement Error-Counter
bne \TF5 ;continue if another attempt
bset d3,VerErrFlag ;set Bit for Error
\TF6: addq.w #1,d3 ;increment Dest.number
cmpi.w #4,d3
bcs \TF1
bra \TF3 ;no additional Drives
\TF5: bsr TrackFastWrite
bra \TF4
\TF3: move.b d4,MotorBits
movem.l (a7)+,d2-d4/a4-a5
rts
TrackFastWrite:
move.l a5,-(a7)
move.l WriteAddrs,a5
move.w SLength,d0
move.w #NoIndex,d1
bsr Writer
move.l (a7)+,a5
rts
DeepCopy:
move.b DD,d0
cmp.b SD,d0
beq \DC1
bra DeepCopyML ;for several Drives
\DC1: bra DeepCopyEL ;for one Drive
DeepCopyEL:
move.b #$aa,ShrtByte ;ShortByte for Chruncher = aa
bsr NextMemory ;assign memory
bsr insert_destination
tst.l d0
bmi \FCEL2
\FCEL9: bsr TestProtect
tst.l d0
bpl \FCEL10
bsr protect_Destination
tst.l d0
bmi \FCEL2 ;Escape activated
bra \FCEL9
\FCEL10: bsr LengthTest
move.w StartTrack,TrackNumS
move.w LenghtDest,d0 ;Length for Cruncher
addi.w #$10,d0
move.w d0,Length
\FCEL11: bsr insert_source
tst.l d0
bmi \FCEL2
\FCEL1: bsr TestProtect
tst.l d0
bmi \FCEL3
bsr protect_Source
tst.l d0
bmi \FCEL2 ;Escape activated
bra \FCEL1
\FCEL3: bsr DeepCopy1DL ;read into memory
tst.l d0
bmi \FCEL2
\FCEL7: move.w TNumBufferA,StartTrack
bsr insert_destination
tst.l d0
bmi \FCEL2
\FCEL5: bsr TestProtect
tst.l d0
bpl \FCEL6
bsr protect_Destination
tst.l d0
bmi \FCEL2 ;Escape activated
bra \FCEL5
\FCEL6: bsr DeepCopy1DS ;Write Tracks
tst.l d0
bmi \FCEL2
cmp.b #ON,ws ;write several times ?
bne \FCEL8 ;no
bsr write_b_again
cmp.w #Escape,ErrorFlag
beq \FCEL2
tst.l d0
bpl \FCEL7 ; write again
\FCEL8: move.w StartTrack,TNumBufferA
move.w TNumBufferE,d0
cmp.w EndTrack,d0
bcs \FCEL11
\FCEL2: rts
DeepCopy1DL:
\FCD1: clr.w ErrorFlag
bsr TrackLS ;load Track from Source
cmp.w #NoDisk,ErrorFlag
beq \Error
move.l TrackBuffer2,a0 ;pass Pointer
move.l WriteAddrs,a1
lea -6(a0),a0
move.l a1,(a0)
move.w SLength,4(a0)
bsr Packe ;crunch Track
tst.l d0
bmi \FCD2 ;Memory full
bsr TextoutL
\FCD3: add.w #1,StartTrack
move.w StartTrack,d0
cmp.w EndTrack,d0
bls \FCD1
\FCD2: subq.w #1,StartTrack
clr.l d0
move.w StartTrack,TNumBufferE ;Last Track
rts
\Error: move.l #-1,d0
rts
;Copy part for writing with one Drive
DeepCopy1DS:
move.w StartTrack,d0 ;first Track read
\FDS1: bsr HeadPos
bsr TextoutS
move.l TrackBuffer2,a0 ;Buffer for Track (Target)
lea -6(a0),a0
bsr EntPacke ;Track again in normal size
move.l TrackBuffer2,a0
move.l -6(a0),WriteAddrs
move.w -2(a0),SLength
move.l #$aaaaaaaa,-4(a0)
bsr TrackWriter
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #DiskProtect,ErrorFlag
bne \FDS3
bsr protect_destination
bra \Error
\FDS3: cmp.b #ON,vd ;Verify ON ?
bne \FDS2 ;branch, when not on
; bsr TrackFVerify
; cmp.w #NoDisk,ErrorFlag
; beq \Error
; cmp.w #VerifyError,ErrorFlag
; bne \FDS2
; bsr WError
\FDS2: addq.w #1,StartTrack
move.w StartTrack,d0
cmp.w TNumBufferE,d0
bls \FDS1
clr.l d0
clr.w FreeFlagCh ;Chip-Mem is free again
clr.w FreeFlagFa ;Fast-Mem is free again
rts
\Error: move.l #-1,d0
rts
DeepCopyML:
bsr SwitchD
\DC5: bsr TestProtect
tst.l d0
bpl \DC3
bsr protect_Destination
tst.l d0
bmi \Error ;Escape activated
bra \DC5
\DC3: bsr LengthTest
tst.l d0
bmi \Error
\DC1:
bsr TextoutL
bsr TrackLS ;load Track from Source
cmp.w #NoDisk,ErrorFlag
beq \Error
bsr SwitchD
move.w StartTrack,d0
bsr HeadPos
bsr TextoutS
bsr TrackWriter
cmp.w #NoDisk,ErrorFlag
beq \Error
cmp.w #DiskProtect,ErrorFlag
bne \DC2
bsr protect_destination
bra \Error
\DC2: add.w #1,StartTrack
move.w StartTrack,d0
cmp.w EndTrack,d0
bls \DC1
\Error: rts
;load Track from Source or Destination.
;>= StartTrack = Track which will be loaded
TrackLS: bsr SwitchS
move.l TrackBuffer1,a5
move.w StartTrack,d0
bsr HeadPos
bsr TrackLoader
rts
;Check length of Source- and Dest.-Diskette
;=>CheckLength = Length of Source-Disk
;=>LenghtDest = Length of Dest.-Disk
LengthTest:
bsr SwitchD
move.w StartTrack,d0
bsr HeadPos
move.l TrackBuffer2,a5
bsr erase
move.w #Bytesread-$15,d0
bsr Writer
tst.l d0
bmi \TD1 ;Disk write protected
bsr Counter
tst.l d0
bmi \TD1 ;No Disk in Drive
move.w CheckLength,LenghtDest
\TD1: rts
;load Track after setting Motor Bits
;>= A5 = Pointer to the Read buffer
;=> WriteAddrs = Pointer to Data for writing
;=> SLength = Number of Bytes to be written
TrackLoader:
move.w #CopyAttempt1,CopyTry1
Attempt1:
move.w #CopyAttempt2,CopyTry2
;Attempts, on NoSync
Attempt2:
;measure length of Track (Index <=> Index)
;rad data without DMA in Buffer starting at A5
move.w #NoError,ErrorFlag
bsr Counter ;=> CheckLength = Length of Track
tst.l d0 ;Disk in Drive?
bmi \TrackLoaderEnd
;measure distance from Index to Sync
;if no Sync, then D0 = -1
;=> Syncwidth = distance to Sync
bsr Syncdistance
tst.l d0
bpl \OK2
sub.w #1,CopyTry2
bne Attempt2
;Program part when no Sync is found
\TL7: move.l TrackBuffer2,a5
bsr CopyOSync
bra \TL11
\OK2:
move.w CheckLength,d0
add.w #$100,d0
move.w #WithSync,d1
bsr loader
move.w SyncWord,(a5) ;store first Sync
;determine number of Bytes to Track (Sync to Sync)
;=> D0 = -1, if number deviates too much from CheckLength
;=> TrackBytes = Length of Track
bsr SrchTEnd
tst.l d0
bpl \TL3
bsr SrchTEnd2
tst.l d0
bpl \TL3
sub.w #1,CopyTry1
bne Attempt1
move.w CheckLength,TrackBytes
sub.w #$10,TrackBytes ;if no End found
;shorten Track
;search for Gap if Sync was found
;>= A5 Pointer to beginning of Track
;=> Size1 = Size of the largest Block
;=> Size2 = Size of the second largest Block
;=> SizePos = Position of the largest Block
;=> SyncNum = Number of Syncs found
\TL3:
clr.l d0
move.w TrackBytes,d0
add.l a5,d0
move.l d0,EndPos
bsr Blockidentify
cmp.w #SortBlockNum,SyncNum
bls \TL2 ;Number of Sync Ok
;Too many Blocks for intermediate memory
move.l SizePos,BegPos ;Gap in largest Block
bra \TL1 ;Too many Blocks to sort
\TL2:
bsr TrackAmiga ;Test if Amiga-Track
tst.l d0
bpl \TL4 ;branch if Amiga-Track
cmp.b #ON,sy ;Sync correction
bne \TL5 ;no
\TL4: bsr Synccorrector
\TL5: bsr OrderBlocks
bsr SearchGap
\TL1: move.l TrackBuffer2,a4 ;Destination for copying
bsr Entirecopy
\TL11: clr.l d0 ;erase Error-Flag
\TrackLoaderEnd:
rts
;load Track which has no Sync
;>= A5 = Track-Buffer
;=> GapLength = Length of Gap
;=> Syncwidth = 0 (no Sync)
;=> TrackBytes = Number of Bytes on the Track
CopyOSync:
movem.l d2-d3,-(a7)
move.w CheckLength,d0
cmp.w #Bytesread-50,d0 ;Source-Track too long
bcc \COS7
add.w #36,d0
bra \COS6
\COS7: move.w #Bytesread-50,CheckLength
move.w #Bytesread-16,d0
\COS6: move.w #WithoutSync,d1
bsr loader
tst.l d0
bmi \COS1
move.w CheckLength,d1
sub.w #50,d1
move.l a5,a0 ;Track-Buffer
move.b (a0)+,d2 ;get first Byte
\COS2: move.b (a0)+,d3
cmp.b d2,d3 ;compare Bytes
bne \COS4 ;not equal
sub.w #1,d1 ;increase number
bne \COS2
bra \COSOK ;Track the same everywhere
\COS4: add.l #2,a0 ;jump over Gap
move.b (a0)+,d2
\COS3:
move.b (a0)+,d3
cmp.b d2,d3 ;compare Bytes
bne \COSNO ;not always the same
sub.w #1,d1 ;increment Counter
bne \COS3
move.l a5,a0
\COSOK: move.w LenghtDest,d0
add.w #$10,d0
\COS5: move.b d2,(a0)+
dbf d0,\COS5
\COSNO: move.w LenghtDest,d0
add.w #$4,d0
move.w d0,TrackBytes
move.w d0,SLength ;number of write bytes
move.l a5,WriteAddrs ;beginning of Data
move.w #NoSync,ErrorFlag
clr.l d0
movem.l (a7)+,d2-d3
rts
\COS1: move.l #-1,d0
rts
TrackWriter:
move.l WriteAddrs,a5
move.w SLength,d0
bsr Writer
rts
erase:
move.l TrackBuffer2,A0
move.w #(Bytesread-$10)/4,d0
\ER2: move.l #$aaaaaaaa,(a0)+
dbf d0,\ER2
rts
;determine copy area (Start- and End-Cylinder)
;>= StartTrack = Track where start is made (Track!!)
;>= EndTrack = Track which is copied last (Track!!)
Start_End: clr.l d0
move.b fc,d0 ;first Cylinder
lsl.b #1,d0 ;Cylinder => Track
move.w d0,StartTrack
move.w d0,TNumBufferA
move.b lc,d0 ;last Cylinder
lsl.b #1,d0 ;Cylinder => Track
add.w #1,d0 ;last Track = bottom side
move.w d0,EndTrack
rts
;test if Disk is in the Drive
;=> D0 = -1, if no Disk in the Drive
DiskInFloppy:
clr.l d0
move.b $bfe001,d0
btst #2,d0
bne \DIF
move.l #-1,d0
move.w #NoDisk,ErrorFlag
\DIF: rts
;load Track
;A5 = Pointer to Data-Buffer
Loader: MOVEM.L d2-d3,-(A7)
move.w d0,d3 ;read Byte num
lsr.w #1,d3
bsr DiskInFloppy
tst.l d0
bmi \L1
MOVE.W #$8010,$DFF096 ;enable Disk-DMA
move.w #$7f00,$DFF09E ;erase Disk-Bits
MOVE.L A5,A1 ;Pointer to Data-Buffer
MOVE.L A1,$DFF020 ;pass Data-Buffer
cmp.w #WithSync,d1
bne \L3
MOVE.W SyncWord,$DFF07E ;pass SYNC-Word
move.w #$8500,$DFF09E
lea 2(a5),a1
move.l a1,$DFF020 ;pass new Address
bra \L4
\L3: MOVE.W #$8100,$DFF09E ;To MFM-Format
\L4: MOVE.W #$4000,$DFF024 ;prepare transmission
bsr Index ;wait to Index
tst.l d0
bmi \L1
or.w #$8000,d3
MOVE.W d3,$DFF024
MOVE.W d3,$DFF024 ;read Data
clr.l d0 ;report Ok
MOVE.L #$18000,D1 ;set time counter
move.w #$0002,$dff09c ;erase Blockdone-Int.
\L2: MOVE.W $DFF01E,D2
BTST #1,D2
BNE.S \L1 ;wait for Disk-Block-Ready
SUBQ.L #1,D1 ;decrement Counter
BNE.S \L2 ;branch when not done
move.l #-1,d0
\L1: MOVE.W #$4000,$DFF024
\L5: MOVEM.L (A7)+,D2-d3
RTS
;wait for Index hole
Index:
move.l d1,-(a7)
clr.l d0
move.l #$30000,d1
MOVE.B $BFDD00,D0
Index1: MOVE.B $BFDD00,D0 ;wait for Index hole
BTST #4,D0
Bne.s Index2
sub.l #1,d1
bne Index1
move.l #-1,d0
Index2:
move.l (a7)+,d1
rts
;determine Motorbits, set Heads to zero
HeadMov:
movem.l d2-d4,-(a7)
clr.w d3
move.b DD,d2 ;Dest.-Drives
or.b SD,d2 ;Source-Drives
\KA1: clr.l d0
btst d3,d2 ;Drive now in use ?
beq \KA2 ;not in use
bset d3,d0 ;Bit for Drive
lsl.b #3,d0
eor.b #$fb,d0
move.b d0,MotorBits
bsr MotorOn
clr.l d0
bsr HeadPos
\KA2:
addq.w #1,d3
cmp.w #4,d3
bne \KA1
bsr MotBits
move.b MotorBitsD,MotorBits
move.b #-1,Flag
clr.w TrackNumS
clr.w TrackNumD
bsr SwitchS
movem.l (a7)+,d2-d4
rts
TestDrive:
move.l a0,-(a7)
lea $bfd000,a0
bclr #1,MotorBits
bsr Stepper
bset #1,MotorBits
bsr Stepper
move.l (a7)+,a0
rts
;=> D0 = -1 => Disk protect
TestProtect: bsr TestDrive
clr.w ErrorFlag
move.b $bfe001,d0
btst #3,d0
bne \TP2
move.w #DiskProtect,ErrorFlag
move.l #-1,d0
bra \TP1
\TP2: clr.l d0
\TP1: rts
;place Head in position indicated by D0
HeadPos: MOVEM.L D0-D3,-(A7)
lea $bfd000,a0
tst.w d0
beq HeadNull
move.w TrackNum,d2 ;current Track-Number
CMP.W d2,D0
BEQ.S Headend ;End when right Track
move.w d0,d3 ;Track-Number to D3
move.b MotorBits,d1
bset #2,d1 ;lower Head
btst #0,d3
beq Upper ;select lower Head
bclr #2,d1
Upper: move.b d1,MotorBits ;upper Head
move.b d1,$100(a0)
move.w d3,TrackNum
lsr.w #1,d2
lsr.w #1,d3 ;calculate steps
sub.w d3,d2
bcs.s In
bhi.s Out
bra Headend
In: bclr #1,d1
move.b d1,MotorBits
neg.w d2
bra.s rechok
Out: bset #1,d1
move.b d1,MotorBits
bra.s rechok
Heads: bsr Stepper
rechok: dbf d2,Heads
Headend: movem.l (a7)+,d0-d3
rts
HeadNull:
move.b Motorbits,d1
bset #2,d1
bset #1,d1
move.b d1,Motorbits
clr.w TrackNum
HeadNull1: move.b $bfe001,d0
btst #4,d0
beq.s \He1
bsr Stepper
bra HeadNull1
\He1: bclr #1,MotorBits
bsr Stepper
bset #1,MotorBits
bsr Stepper
bra Headend
Stepper:
move.b MotorBits,d0
lea $100(a0),a1
move.b d0,d1
bclr #0,d0
move.b d0,(a1)
nop
nop
move.b d1,(a1)
jsr Timer
move.b MotorBits,(a1)
rts
;Wait loop
Timer: MOVE.L D7,-(A7)
MOVE.W #2500,D7
\L1: DBRA D7,\L1
MOVE.L (A7)+,D7
RTS
Timer2: MOVE.L D7,-(A7)
MOVE.L #$6000,D7
\L1: sub.l #1,D7
bne \L1
MOVE.L (A7)+,D7
RTS
;Motor routine: D0=0 => Motor off
MotorOff: clr.l d0
bra Motor
MotorOn: move.b #$01,d0
Motor: movem.l d1/d2,-(a7)
lea $bfd000,a0
tst d0
seq d1
andi.b #$80,d1
move.b MotorBits,d2
andi.b #$80,d2
cmp.b d1,d2
beq.s Mook
bclr #7,MotorBits
or.b d1,MotorBits
move.b #$ff,d1
eor.b d2,d1
move.b d1,$100(a0)
move.b MotorBits,$100(a0)
btst #7,MotorBits
bne Mook
jsr Timer2
Mook: movem.l (a7)+,d1/d2
rts
Disable: move.w #$4000,$dff09a
move.l a6,-(a7)
move.l $4,a6
add.b #1,IDNestCnt(a6)
move.l (a7)+,a6
rts
Enable: move.l a6,-(a7)
move.l $4,a6
sub.b #1,IDNestCnt(a6)
bge L005
move.w #$c000,$dff09a
L005: move.l (a7)+,a6
rts
;Waits for Byte during read and stores Byte (a0)+
rts
;>= a0 = Address of data to be found
;>= A1 = Address where search starts
;>= Searchln = Number of words for error
;>= NumWords = Number of Words which is compared
;=> D1 = Number of Bytes to fund
;=> Position = where found
;=> D0 = -1 = not found
;=> A0 = Position where found
Bitsrch:
movem.l d2-d6/a2-a4,-(a7)
move.l a0,a2
move.l a1,a3
clr.w d5
move.w Searchln,d4 ;Search num
srch2: move.w #00,d3 ;number of shift Bits
srch1: move.l (a2),d1
move.l (a3),d2
bsr comp
tst.w d0
beq srchok
move.l a0,a2
tst.w d5
beq srch4
clr.w d5
move.w d6,d3
move.l a4,a3
srch4: add.w #1,d3
cmp.w #$10,d3
bne srch1
srch3: add.l #2,a3
clr.w d5 ;compare the right ones
dbf d4,srch2 ;Counter for attempts
move.l #-1,d0 ;not found
bra srchend
srchok:
tst.w d5
bne srchok2
move.l a3,a4
move.w d3,d6
srchok2: add.w #1,d5
cmp.w NumWords,d5
beq srchend1
add.l #2,a2
add.l #2,a3
bra srch1
srchend1: move.l #0,d0
sub.w #1,d5
lsl.w #1,d5
suba.l d5,a3
move.l a3,a0
move.l a3,Position
move.l a3,a0 ;Position
move.w d3,BitShifts ;Bit shifting
sub.l a1,a3
move.l a3,d1 ;Number of Bytes until found
srchend: movem.l (a7)+,d2-d6/a2-a4
rts
comp: movem.l d1-d2,-(a7)
lsl.l d3,d2
swap d1
swap d2
eor.w d1,d2
move.w d2,d0
movem.l (a7)+,d1-d2
rts
MotBits:
move.b SD,d0 ;Source-Disk
lsl.b #3,d0
eor.b #$fb,d0
move.b d0,MotorBitsS
move.b DD,d0 ;Dest.-Disk
lsl.b #3,d0
eor.b #$fb,d0
move.b d0,MotorBitsD
rts
;switch on next Dest.-Drive
;!!! Caution !!! old Motorbits are reset
;>= D1 = which Drive ( < 4)
;=> D0 = -1, if no additional Drive available
;=> D0 = Null if OK
SwitchND:
move.l d2,-(a7)
clr.l d0
move.b DD,d2
btst d1,d2 ;Drive connected ?
bne \SND1 ;yes, connected
move.l #-1,d0
bra \SND2
\SND1: bset d1,d0 ;Bit for Drive
lsl.b #3,d0
eor.b #$7b,d0
move.w StartTrack,d1
bset #2,d0
btst #0,d1
beq \SND3 ;lower Head select
bclr #2,d0
\SND3: move.b d0,MotorBits ;upper Head
move.b d0,$bfd100
clr.l d0
\SND2: move.l (a7)+,d2
rts
SwitchS:
tst.b Flag
bpl \S1
move.b MotorBits,MotorbitsD
move.w TrackNum,TrackNumD
move.b MotorBitsS,MotorBits
move.w TrackNumS,TrackNum
move.b #$7f,$bfd100
move.b MotorBits,d0
bclr #7,d0
move.b d0,$bfd100
move.b d0,MotorBits
clr.b Flag
\S1: rts
SwitchD:
tst.b Flag
bmi \S1
move.b MotorBits,MotorbitsS
move.w TrackNum,TrackNumS
move.b MotorBitsD,MotorBits
move.w TrackNumD,TrackNum
move.b #$7f,$bfd100
move.b MotorBits,d0
bclr #7,d0
move.b d0,$bfd100
move.b d0,MotorBits
move.b #-1,Flag
\S1: rts
;store Track
;>= D0 = number of Bytes to write
;>= A5 = Track-Buffer
;>= D1 = Indication if wait for Index (IndexOk/NoIndex)
Writer: MOVEM.L D2-D3,-(A7)
move.w d1,d2
move.w d0,d3 ;Number to D3
clr.w ErrorFlag
bsr DiskInFloppy
tst.l d0
bmi \Protect
move.b $bfe001,d0
btst #3,d0
bne \SR5
move.w #DiskProtect,ErrorFlag
bra \Protect
\SR5: lsr.w #1,d3 ;from Byte make Word
jsr MotorOn
MOVE.W #2,$DFF09C ;erase Disk-Block-Int.
MOVE.L A5,$DFF020 ;pass Data-Buffer
MOVE.W #$8210,$DFF096 ;enable Disk-DMA
move.w #$7f00,$dff09e
MOVE.W #$8100,$DFF09E ;MFM-Format
cmp.w #80,StartTrack
bcs \SR1
move.w #$a000,$dff09e ;Pre-compensation
\SR1: MOVE.W #$4000,$DFF024 ;prepare transmission
cmp.w #NoIndex,d2
beq \SR2
bsr Index
tst.l d0
bmi \Protect
\SR2: or.w #$c000,d3 ;switch to write
MOVE.W d3,$DFF024
MOVE.W d3,$DFF024 ;write Data
clr.l d0 ;pass OK message
MOVE.L #$20000,D1 ;set time counter
\SR3: MOVE.W $DFF01E,D2
BTST #1,D2
BNE.S \SR4 ;wait for Disk-Block-Ready
SUBQ.L #1,D1 ;decrement Counter
BNE.S \SR3 ;branch when not done
\Protect: move.l #-1,d0
\SR4: move.w #$4000,$dff024
MOVEM.L (A7)+,D2-D3
RTS
;Searches for Track-End when Sync found
;>= A5 = Pointer to Track-Buffer (Sync found)
;=> TrackBytes = Number of Bytes on the Track (seek for Sync)
;=> D0 = -1, too much deviation from CheckLength
SrchTEnd:
move.l a5,a0
clr.l d0
move.w CheckLength,d0
sub.w #$4,d0
adda.l d0,a0
move.w #$10,d0
bsr SrchSync
tst.l d0
bmi \STE2
suba.l a5,a0
sub.w #2,a0
move.w a0,TrackBytes
rts
\STE2: move.l #-1,d0
move.w #LengthUnequal,ErrorFlag
rts
SrchTEnd2:
move.l a5,a0
adda.l #$04,a0
move.l a0,a1
clr.l d0
move.w CheckLength,d0
sub.w #$40,d0
adda.l d0,a1
move.w #$40,Searchln
move.w #$60,NumWords
bsr Bitsrch
tst.l d0
bmi \STE2
suba.l a5,a0
suba.l #6,a0 ;Position before Sync
move.w a0,TrackBytes
rts
\STE2: move.l #-1,d0
move.w #LengthUnequal2,ErrorFlag
rts
;search for Blocks and store
;>= A5 = Pointer to Track beginning
;=> Size1 = Size of the largest Block
;=> Size2 = Size of the second largest Block
;=> SizePos = Position of the largest Block
;=> SyncNum = Number of Syncs found
;=> Blocks = Buffer in which the Block sizes are stored
Blockidentify: movem.l d2-d4/a3,-(a7)
move.w TrackBytes,d2 ;Bytes on Track
move.l a5,a3 ;Beginning of Track
clr.w Size1
clr.w Size2
clr.w SyncNum
clr.w d3
\S2: move.w d2,d0
move.l a3,a0 ;where to start search
bsr SrchSyncF
tst.l d0
bmi \S5 ;End
tst.w d1
beq \S6
move.w d3,d4
add.w d1,d3 ;Number + Sync
bsr Blockentry
bsr Size
clr.w d3 ;Sync gap = 0
\S6:
add.w #2,d3 ;Sync gap +2
add.w #2,d1
andi.l #$ffff,d1
adda.l d1,a3
sub.w d1,d2
bcc \S2
bra \S7
\S5: move.w d2,d1
add.w #2,d1 ;Number +2
move.w d3,d4 ;Sync message
add.w d1,d3 ;Number + Syn
bsr Blockentry
bsr Size
\S7: movem.l (a7)+,D2-d4/A3
rts
;Enter size of Blocks
;>= D1 = Block size
Size:
cmp.w Size1,d3
bcs \S3
move.w Size1,Size2
move.w d3,Size1
move.l a0,a1
move.l a1,SizePos
bra \S4
\S3: cmp.w Size2,d3
bcs \S4
move.w d1,Size2
\S4: rts
Blockentry:
move.w SyncNum,d0
cmp.w #$40,d0 ;Too many Blocks ?
bcc \S1 ;yes, do not store
lsl.w #2,d0
lea Blocks,a1
lsr.w #1,d4
move.w d4,(a1,d0)
add.w #2,d0
move.w d3,(a1,d0) ;store Block
\S1: add.w #1,SyncNum
rts
;seek Sync-Mark (fast)
;>= A0 = Search address
;>= D0 = Byte number for errors permitted
;=> A0 = Sync address
;=> D0 = -1, no Sync found
;=> D1 = found after xx Bytes
SrchSyncF:
lsr.w #1,d0 ;from Byte make Word
move.l a0,a1
\SSF2: cmp.w #$4489,(a0)+
beq \SSF1
dbf d0,\SSF2
move.l #-1,d0
bra \SSF3
\SSF1: suba.l #2,a0
move.l a0,d0
sub.l a1,a0
move.w a0,d1
move.l d0,a0
clr.l d0
\SSF3: rts
;search for Sync-Mark
;>= A0 = Search address
;>= D0 = Byte number for errors permitted
;=> A0 = Sync address
;=> D0 = -1, no Sync found
;=> D1 = found after xx Bytes
;=> BitShifts = shifted by xx Bits
SrchSync:
movem.l d2-d4/a2,-(a7)
move.l a0,a2
lsr.w #2,d0 ;Byte out, with longword value
lea SyncBase,a1
\SS3: clr.l d1
move.l #$ffff0000,d3
move.l (a0)+,d2
\SS2: move.l d2,d4
and.l d3,d4
cmp.l (a1,d1),d4
beq \SS1
add.w #4,d1
lsr.l #1,d3
cmp.w #$40,d1
bls \SS2
dbf d0,\SS3
move.l #-1,d0
bra \SS4
\SS1: clr.l d0
lsr.w #2,d1
move.w d1,BitShifts
cmp.w #$8,d1
bcc \SS5
suba.l #2,a0
\SS5: suba.l #2,a0
move.l a0,d1
suba.l a2,a0
exg.l a0,d1
\SS4: movem.l (a7)+,d2-d4/a2
rts
;Distance Index <=> Sync
;=> Syncwidth = Distance Index <=> Sync
;=> D0 = -1, no Sync found
Syncdistance:
move.l a5,a0
move.w CheckLength,d0
bsr SrchSync
tst.l d0
bpl \SE1
move.w #NoSync,ErrorFlag
bra \SE2
\SE1:
move.w d1,Syncwidth
\SE2: rts
;A5 = TrackBuffer
;Counter of Data on Disk without Sync and without DMA
;>= A5 = Pointer to Verify-Buffer for reading Data without Sync
;=> CheckLength = Length of a Track (From Index to Index)
Counter:
bsr DiskInFloppy
tst.l d0
bmi \Z5
movem.l d2-d4/a2-a3,-(a7)
move.w #$0600,$dff09e ;switch Sync off
move.w #$8000,$dff024
lea $dff01b,a0
lea $dff01a,a1
lea $bfdd00,a2
move.l #15,d2
move.l #4,d3
move.w #1,d4
clr.w d0
move.b (a2),d1 ;erase Byte-Ready-Flag
\Z4: move.b (a2),d1
btst #4,d1
beq.s \Z4
move.w (a1),d1 ;erase Byte-Ready-Flag
move.b (a2),d1 ;erase Indexbit
move.l a5,a3
\Z1:
btst d2,(a1)
beq.s \Z1
btst d3,(a2)
bne.s \Z2
add.w d4,d0
move.b (a0),(a3)+
bra \Z1
\Z2:
andi.w #$fffe,d0
move.w d0,CheckLength
cmp.w #Bytesread,d0 ;Track too long
bcs \Z6
move.w #Bytesread-16,CheckLength
\Z6: bclr #31,d0 ;erase Errorbit
movem.l (a7)+,d2-d4/a2-a3
\Z5: move.w #$4000,$dff024
rts
;Sort Block sizes
OrderBlocks:
move.l d2,-(a7)
cmp.w #SortBlockNum,SyncNum
bhi \OBEND ;too many Blocks
tst.w SyncNum
beq \OBEND ;no Blocks
clr.w NumSortBlock
lea Blocks,a0
move.w SyncNum,d0
\OB5: move.l (a0)+,d1
sub.w #1,d0
lea SortBlocks,a1 ;Number of Blocks -1
move.w NumSortBlock,d2
tst.w d2
beq \OB2 ;first Block
\OB4: cmp.w (a1)+,d1
bne \OB3 ;found
add.w #1,(a1)
bra \OB6
\OB3: adda.w #2,a1
sub.w #1,d2
bne \OB4 ;continue search
\OB2: move.w d1,(a1)+
move.w #1,(a1)+
add.w #1,NumSortBlock
\OB6: tst.w d0
bne \OB5 ;new search
\OBEND: move.l (a7)+,d2
rts
SearchGap:
move.l d2,-(a7)
clr.l BegPos
move.w NumSortBlock,d0
cmp.b #1,dc1
beq \SL10 ;DeepCopy 1 (Gap after large Block)
;search for single Blocks
sub.w #1,d0 ;Block number -1
\SL3:
bsr SingleBlock ;search for single Block
tst.l d0 ;Gap found ?
bpl \SL7 ;branch when not found
\SL10: move.l SizePos,a0 ;Gap with largest Block
\SL7:
move.l A0,BegPos
cmp.l EndPos,a0
bcs \SL8
move.l a5,a0
move.l a0,BegPos
\SL8:
move.l SizePos,d0
cmp.l EndPos,d0
bcs \SL9
move.l a5,SizePos
\SL9: move.l (a7)+,d2
rts
;Search for single Block
;=> D0 = Block number
;=> D0 = Block number of next Block
;=> D0 = -1, when none found
;=> D1 = Size of Block
;=> a0 = Address of the Blocks
SingleBlock:
movem.l d2-d4,-(a7)
and.l #$ffff,d0 ;erase error message
tst.w d0
bmi \EB3
lea SortBlocks,a0
\EB2: move.w d0,d1
lsl.w #2,d1
move.l (a0,d1),d2
cmp.w #1,d2
beq \EB1 ;Block found
sub.w #1,d0
tst.w d0
bpl \EB2
\EB3: move.l #-1,d0
bra \EBEND ;Error
\EB1: move.w (a0,d1),d2 ;Block length
clr.w d3 ;erase Blockadr.
lea Blocks,a0
\EB4: move.l (a0)+,d1
add.w d1,d3 ;determine Address
cmp.w d1,d2
bne \EB4 ;continue if not done
sub.l a0,a0 ;clear A0
\EB5: move.w d3,a0 ;Offset
add.l a5,a0 ;Address
move.w d2,d1 ;Block size
sub.w #1,d0 ;Number of next Block
\EBEND: movem.l (a7)+,d2-d4
rts
;Test if Track on Amiga-Format
;=> D0 = Null, if Track Amiga-Format
;=> D0 = -1, if not Amiga-Format
TrackAmiga:
move.l d2,-(a7)
lea Blocks,a0 ;Pointer to Block storage
cmp.w #$0b,SyncNum ;SyncNumahl for Amiga-Format
bne \PL1 ;No not Amiga-Format
clr.w d1
clr.l d2
move.w #$0a,d0
\PL3: move.w d0,d2
lsl.w #2,d2
cmp.w #$0440,2(a0,d2) ;Block length for Amiga
bne \PL2
add.w #1,d1
\PL2: dbf d0,\PL3
cmp.w #$9,d1 ;at least 9 Amiga-Blocks
bcs \PL1
clr.l d0 ;OK, Amiga-Format
move.b #ON,AmigaTrack
\PL4: move.l (a7)+,d2
rts
\PL1: move.l #-1,d0 ;not Amiga-Format
move.b #OFF,AmigaTrack
bra \PL4
;The program assumes that all Syncs are equal in length
;all Syncs are fitted to the first
;>= A5 = Pointer to Track-Buffer
Synccorrector:
movem.l d2-d4,-(a7)
cmp.w #1,SyncNum
beq \SK1 ;only one Sync
lea Blocks,a0
clr.w d0
clr.l d3
move.l a5,a1
move.l (a0)+,d2
move.w d2,d3 ;Block length
swap d2 ;Sync value
\SK3: adda.l d3,a1 ;Pointer to Block
add.w #1,d0
cmp.w SyncNum,d0
bcc \SK1
move.l (a0)+,d1
move.w d1,d3 ;Block length
swap d1 ;SyncNum from Block
cmp.w d2,d1
bcc \SK3 ;do not correct
sub.w d2,d1
not.w d1
move.w d1,d4 ;Number of new Syncs
move.l a1,-(a7)
\SK2:
cmp.l SizePos,a1 ;must Pos be changed
bne \SK8
sub.l #2,SizePos ;change SizePos
\SK8: move.w #$4489,-(a1)
dbf d4,\SK2
move.l (a7)+,a1
add.w #1,d1
add.w d1,-4(a0)
lsl.w #1,d1
sub.w d1,-6(a0)
add.w d1,-2(a0)
bra \SK3
\SK1: cmp.w #LengthUnequal,ErrorFlag
beq \SK7 ;no end correction required
move.w d2,d0 ;Sync value
move.l EndPos,a1
add.l #2,a1 ;set Pointer to Sync
bra \SK4
\SK6: cmp.w #$4489,(a1)+ ;test transition to beginning
bne \SK5
\SK4: dbf d0,\SK6
\SK7: movem.l (a7)+,d2-d4
rts
\SK5: sub.w d0,d2
lsl.w #1,d2
sub.l #2,EndPos
sub.w #2,TrackBytes
sub.w #2,-2(a0) ;Last Block is shorter
bra \SK7
;after the Gap has been determined, the Data are copied
;and written
;>= A5 = TrackBuffer (Source)
;>= A4 = TrackBuffer (Destination)
Entirecopy:
move.l a2,-(a7)
move.l a4,a1
move.l BegPos,a0
sub.l a5,a0 ;Offset of the beginning
clr.l d0
move.w Syncwidth,d0
sub.w #$0044,d0 ;distance correction
bcc \UK6 ;distance too small ?
clr.w d0 ;yes, distance = 0
\UK6:
add.l d0,a0 ;distance from Index
move.w a0,Offset ;number of Bytes before Sync
suba.l a0,a1 ;beginning of writing
move.l a1,WriteAddrs
move.w TrackBytes,d0
lsr.w #1,d0 ;Byte to Word
move.w LenghtDest,d1
move.l BegPos,a0 ;Source-Address
move.l a4,a1 ;Destination-Address
cmp.b #ON,AmigaTrack
bne \UK9
add.l #4,a1
\UK9: move.l #$aaaaaaaa,-4(a1)
\UK4: move.w (a0),(a1)+
sub.w #1,d1
cmp.l EndPos,a0
bcs \UK3
move.l a5,a0
bra \UK5
\UK3: adda.l #2,a0
\UK5: dbf d0,\UK4
move.l (a7)+,a2
and.w #$f000,d1
bne \UK8 ;Source longer than Destination
\UK7: move.w #$aaaa,(a1)+ ;if Dest. is longer than Source
dbf d1,\UK7
\UK8: move.w LenghtDest,d0
sub.w #$0006,d0
add.w Offset,d0
move.w d0,SLength
rts
;read Track and decode
;>= A4 = Pointer to Buffer for decoded Data
;>= A5 = Pointer to Buffer for coded Data
FastReads:
MOVEM.L D2-D4/a3/a6,-(A7)
lea decode,a3 ;Jump point for decode
move.w #$080,DecodeCnt ;number of
;Longwords to decode
lea $40(a5),a0
move.l a0,DecodeAdr ;Data area of first Block
adda.l #$400,a0
move.l a0,FTestAdr ;Address of the next Block
move.w #OFF,VerifyFlag
bra Fread
FastVerify: movem.l d2-d4/a3/a6,-(a7)
lea FVerify,a3 ;Jump point for Verify
move.l a5,DecodeAdr
lea $440(a5),a0
move.l a0,FTestAdr
move.w #ON,VerifyFlag
Fread:
clr.w ErrorFlag
bsr DiskInFloppy
tst.l d0
bmi \FastError
MOVEA.L A5,A6 ;Track-Buffer
move.l #$aaaaaaaa,(a6)+
move.w #$4489,(a6)+ ;enter first Sync
bsr search
tst.l d0
bmi \FreadEnd
bsr FErase ;prepare Track-Buffer
clr.l d2
move.w BytesBefGap,d2 ;display Byte before Gap
tst.l d2
beq \FL1 ;No Byte before Gap
clr.w BlockAdr ;Offset in Block
bsr Readbyte ;read Byte
clr.l d0
move.w BytesBefGap,d0
move.l a5,a6
adda.l d0,a6 ;Pointer to next Buffer
move.l #$aaaaaaaa,(a6)+
move.w #$4489,(a6)+ ;enter first Sync
\FL1: move.w BytesAftGAp,d2
tst.l d2
beq \FL2
clr.w BlockAdr
bsr Readbyte
\FL2: cmp.w #ON,VerifyFlag
beq \FL3
bsr lastblock ;no last Block during Verify
\FL3: BTST #2,$BFE001
BEQ.S \FastError ;Error, if no Disk
MOVEQ #0,d0 ;OK-Message
move.l #$aaaaaaaa,$2ec0(a5)
;create Gap after Data
bra \FreadEnd
\FastError: move.l #-1,d0
\FreadEnd: MOVEM.L (A7)+,D2-D4/a3/A6
RTS
;prepare Track-Buffer (erase Block starts)
;>= A5 = Pointer to Track-Buffer
FErase: move.l a5,a0
move.w #10,d1
clr.l d0
\L1: move.l d0,$440(a0)
adda.l #$440,a0
dbf d1,\L1
lea BlockMessage,a0
move.w #10,d1
\L2: clr.w (a0)+
dbf d1,\L2
rts
;read number of Bytes selected
;>= A6 = Pointer to Destination
;>= D2 = Number of Bytes to be read
Readbyte:
jsr install
MOVE.W D2,D0
LSR.W #1,D0
ORI.W #$8000,D0
add.w #1,d0
MOVE.W D0,36(A1)
MOVE.W D0,36(A1)
jsr (a3)
LEA $DFF000,A1
MOVE.W #$4000,$24(A1)
rts
;preparation for reading
;>= A6 Pointer to Track-Buffer
install: LEA $DFF000,A1
move.w #$4000,$24(a1) ;reset Disk-Len
move.w #$8400,$9e(a1) ;switch on Disk-Sync
move.w #$4489,$7e(a1) ;SYNC-Mark
MOVE.L A6,$20(A1) ;pass Buffer
move.w #$0002,$dff09c
rts
;code Longword and store in Buffer
;>= D0 = Longword
;>= A0 = Pointer to Buffer
CodeLWord: MOVEM.L D2-D3,-(A7)
MOVE.L D0,D3
LSR.L #1,D0
BSR \CH1
MOVE.L D3,D0
BSR \CH1
BSR SetBorders
MOVEM.L (A7)+,D2-D3
RTS
\CH1: ANDI.L #$55555555,D0
MOVE.L D0,D2
EORI.L #$55555555,D2
MOVE.L D2,D1
LSL.L #1,D2
LSR.L #1,D1
BSET #$1F,D1
AND.L D2,D1
OR.L D1,D0
BTST #0,-1(A0)
BEQ.S \CH2
BCLR #$1F,D0
\CH2: MOVE.L D0,(A0)+
RTS
;set borders properly
SetBorders: MOVE.B (A0),D0
BTST #0,-1(A0)
BNE.S \CH4
BTST #6,D0
BNE.S \CH6
BSET #7,D0
BRA.S \CH5
\CH4: BCLR #7,D0
\CH5: MOVE.B D0,(A0)
\CH6: RTS
;determine Checksum for Data area
;>= D1 = number of Bytes (must always be divisible by 4)
;>= A0 = Pointer to Buffer
;=> D0 = Checksum
TestSum: MOVE.L D2,-(A7)
LSR.W #2,D1
SUBQ.W #1,D1
MOVEQ #0,D0
\PS1: MOVE.L (A0)+,D2
EOR.L D2,D0
DBRA D1,\PS1
ANDI.L #$55555555,D0
MOVE.L (A7)+,D2
RTS
;decode Block-Header
;>= A0 is Pointer to Header
;=> D0 = Header
Header: move.l (a0)+,D0
move.l (a0)+,D1
andi.l #$55555555,d0
andi.l #$55555555,d1
lsl.l #1,D0
or.l D1,D0
rts
;find first undisturbed Block
;=> A6 = Pointer to Track-Buffer
;=> D0 = Null: Block found
;=> BytesBefGap = Number of Bytes before the Gap
;=> BytesAftGAp = Number of Bytes after the Gap
search:
movem.l d2-d4,-(a7)
move.w #11,d2 ;Number of errors permitted
\SU1: bsr install
move.w #$8024,d0 ;read $24-Words
MOVE.W D0,$dff024
MOVE.W D0,$dff024
bsr Blockready ;wait for Block-Ready
tst.l d0 ;Error, then D0 = -1
bmi \SUError
lea 8(a5),a0 ;Pointer to Block-Header
moveq #$28,d1 ;number of Long words
bsr TestSum ;Sum for Header
move.l d0,d3 ;save Sum
lea 48(a5),a0 ;*Sum
bsr Header ;get Sum from Header
cmp.l d0,d3 ;compare Sums
bne \SUNeu
lea 8(a5),a0
jsr Header ;decode Header
move.w d0,d3 ;Header to D3
lsr.w #8,d3
andi.w #$00ff,d3 ;isolate Sector number
addi.w #1,d3 ;increment Sector number
cmp.w #$000a,d3 ;Number bigger than 10?
bls \SU2 ;No, OK
clr.w d3 ;Number = 0
\SU2: move.w d3,SectNum ;store Number
move.w d3,FirstBlock ;Number first Block
move.w d0,d3 ;Header
andi.w #$ff,d3 ;Sectors to Gap
cmp.b #$0c,d3 ;Header OK?
bcs.s \SUok
\SUNeu: dbf d2,\SU1
bra \SUError
\SUok:
sub.w #1,d3 ;number of Blocks to Gap
move.w d3,d2
move.w #$000b,d4
sub.b d2,d4 ;Number of Blocks after Gap
mulu #$440,d3 ;Number of Bytes to Gap
mulu #$440,d4 ;Number of Bytes after Gap
clr.l d0
move.w d3,BytesBefGap
move.w d4,BytesAftGAp
move.w #$0b,SectBL ;Sectors before Gap after loading
bra \SUEnd
\SUError: move.l #-1,d0
move.w #ReadError,ErrorFlag
\SUEnd: movem.l (a7)+,d2-d4
rts
Blockready: clr.l d0 ;erase Error-Flag
move.l #$20000,d1
move.w #$0002,$dff09c ;erase Disk-Int.
\B1: MOVE.W $DFF01E,D0
BTST #1,D0
bne.s \B2
sub.l #1,d1
bne \B1
move.l #-1,d0 ;Error occurred
\B2: RTS
;decode Bytes until Block has been read
decode:
movem.l d2-d3/a2,-(a7)
clr.l d3
move.w BlockAdr,d3 ;Offset in Block
move.l FTestAdr,a0 ;Address for testing if
;Block already loaded
move.l DecodeAdr,a2 ;Address where
;decoding is done
move.w DecodeCnt,d2 ;Number for decoding
\DC1: MOVE.W $DFF01E,D0
BTST #1,D0 ;area already read
bne \DCEnd ;Yes, End
tst.l (a0) ;TestAdr
beq \DC1 ;wait until Block has been read
movem.l a0-a1,-(a7) ;save Register
lea -$40(a2),a1 ;* Block start
bsr BlockCheck ;check Block
movem.l (a7)+,a0-a1 ;restore Register
move.w SectNum,d0
mulu #$200,d0
move.l a4,a1 ;Base address for destination data
add.l d0,a1 ;Address of the Block
\DC2:
MOVE.W $DFF01E,D0
BTST #1,D0
bne.s \DCEnd ;area already read
move.l (a2),D0
move.l $200(a2),D1
adda.l #4,a2
andi.l #$55555555,d0
andi.l #$55555555,d1
lsl.l #1,D0
or.l D1,D0
move.l d0,(a1,d3) ;enter Longword
addq.w #4,d3
subq.w #1,D2 ;Decode number
bne \DC2
adda.l #$240,a2 ;increment Address
adda.l #$440,a0 ;TestAdr
move.l #$080,D2 ;Decode number
clr.w d3 ;Offset to Null
add.w #1,SectNum ;increment Sector number
cmp.w #$0b,SectNum ;Number more than 10?
bcs \DC3 ;No, OK
clr.w SectNum ;Nummer = 0
\DC3: bra \DC1
\DCEnd:
move.w d3,BlockAdr
move.l a2,DecodeAdr
move.l a0,FTestAdr
move.w D2,DecodeCnt
movem.l (a7)+,d2-d3/a2
RTS
;decode last Block
Lastblock:
movem.l d2-d3/a2,-(a7)
move.w SectNum,d0
mulu #$200,d0
move.l a4,a1 ;Base address for destination data
add.l d0,a1 ;Address of the Block
clr.l d3
move.l DecodeAdr,a2
move.w DecodeCnt,d2
\LB1: move.l (a2),D0
move.l $200(a2),D1
adda.l #4,a2
andi.l #$55555555,d0
andi.l #$55555555,d1
lsl.l #1,D0
or.l D1,D0
move.l d0,(a1,d3)
addq.w #$4,d3
subq.w #1,D2 ;Decode number
bne \LB1
movem.l (a7)+,d2-d3/a2
RTS
;test Block for Error
;A1 = Pointer to start of Block
BlockCheck:
movem.l d2-d3,-(a7)
clr.l d3
move.w SectNum,d3
lsl.w #1,d3 ;Sector number => Offset
lea BlockMessage,a0
move.w (a0,d3),d0 ;get entry
tst.w d0 ;already tested ?
bne \CBEnd2 ;yes, End
lea 64(a1),a0
move.w #$400,d1
jsr TestSum ;Sum for Data block
move.l d0,d2 ;save Sum
lea 56(a1),a0 ;Pointer to Data sum
jsr Header ;decode Sum
cmp.l d0,d2
bne \DataFalse
lea 8(a1),a0
bsr Header ;decode Header
move.w d0,d2 ;store lower Word
lsr.w #8,d2 ;Sector number to d2
cmp.b SectNum+1,d2 ;right Sector
bne \FalseSector
swap d0 ;Track-Number to D0
cmp.b StartTrack+1,d0 ;right Track?
bne \FalseTrack
andi.l #$ff00,d0
cmp.w #$ff00,d0
bne \NotDOSTrack
lea 8(a1),a0
moveq #$28,d1 ;number of Longwords
bsr TestSum ;Sum for Header
move.l d0,d2 ;save Sum
lea 48(a1),a0 ;*Sum
bsr Header ;get Sum from Header
cmp.l d0,d2 ;compare Sums
bne \HeaderFalse
move.w #$ffff,d0
\CBEnd1: lea BlockMessage,a0
move.w d0,(a0,d3)
btst #0,-1(a1)
beq \CB1
move.l #$2aaaaaaa,(a1)
bra \CB2
\CB1: move.l #$aaaaaaaa,(a1)
\CB2: move.l #$44894489,4(a1)
move.w #$ff00,d0 ;create new Header
move.b StartTrack+1,d0
swap d0
move.b SectNum+1,d0
lsl.w #8,d0
move.b SectBL+1,d0
lea 8(a1),a0
bsr CodeLWord ;store Header
lea 8(a1),a0
moveq #$28,d1 ;Longword number
bsr TestSum ;Sum for Header
lea 48(a1),a0 ;*Sum
bsr CodeLWord ;store Checksum
subq.w #1,SectBL
\CBEnd2: movem.l (a7)+,d2-d3
rts
\FalseSector: move.w #$0001,d0
bra \Flagset
\FalseTrack: move.w #$0002,d0
bra \Flagset
\NotDOSTrack: move.w #$0017,d0
bra \Flagset
\HeaderFalse: move.w #$001b,d0
bra \Flagset
\DataFalse: move.w #$0019,d0
\Flagset: move.w #ReadError,ErrorFlag
bra \CBEnd1
;compare Bytes read with old
;>= A4 = Pointer to Base address of the old Block
FVerify:
cmp #VerifyError,ErrorFlag
beq \FVEnd2
movem.l d2-d3/a2,-(a7)
clr.l d3
move.w BlockAdr,d3 ;Offset in Block
move.l FTestAdr,a0 ;Address for test if
;Block already loaded
move.l DecodeAdr,a2 ;Address, where comparison
;is made
\FV1: MOVE.W $DFF01E,D0
BTST #1,D0 ;area already read
bne \FVEnd ;Yes, End
tst.l (a0) ;TestAdr
beq \FV1 ;Wait until Block was read
move.w #$110,d2 ;comparison number
move.w SectNum,d0
sub.w FirstBlockSp,d0
bcc \FV2
addi.w #11,d0
\FV2:
mulu #$440,d0
move.l a4,a1 ;Base address for destination data
add.l d0,a1 ;Address of the Block
\FV3:
move.l (a2)+,d0
cmp.l (a1,d3),d0
beq \FV6 ;Verify Ok
;test for special case ($aaaaaaaa and $2aaaaaaa)
move.l (a1,d3),d1
eor.l d1,d0
cmp.l #$80000000,d0
bne \FV5
\FV6: addq.w #4,d3
subq.w #1,d2
bne \FV3
adda.l #$440,a0 ;TestAdr
clr.l d3 ;Offset to Null
add.w #1,SectNum ;increment Sector number
cmp.w #$0b,SectNum ;Number higher than 10?
bcs \FV1 ;No, OK
clr.w SectNum ;Number = 0
bra \FV1
\FV5: move.w #VerifyError,ErrorFlag
bra \FVEnd3
\FVEnd:
clr.w ErrorFlag
move.w d3,BlockAdr
move.l a2,DecodeAdr
move.l a0,FTestAdr
\FVEnd3: movem.l (a7)+,d2-d3/a2
\FVEnd2: RTS
;code Track
;>= A0 = Pointer to Source
;>= A1 = Pointer to Destination
;>= D0 = Track-Number
CodeTrack:
movem.l d2-d4/a2-a3,-(a7)
move.l d0,d4
move.l a0,a2
move.l a1,a3
moveq #$0b,d2
clr.w d3
\CT1: move.w #$ff00,d0
move.b d4,d0
swap d0
move.w d3,d0
lsl.w #8,d0
move.b d2,d0
move.l a2,a0 ;Source
move.l a3,a1 ;Destination
bsr ConstructBlock
add.l #$440,a3
add.l #$200,a2
addq.w #1,d3
subq.w #1,d2
bne \CT1
movem.l (a7)+,d2-d4/a2-a3
rts
;code Block and create Header
;>= A0 = Uncoded Data (Source)
;>= A1 = Data buffer for coded Data (Destination)
;>= D0 = uncoded Header
ConstructBlock: MOVEM.L D2/A2/A4,-(A7)
MOVEA.L A1,A4
MOVEA.L A0,A2
MOVE.L D0,D2
MOVEQ #0,D0
LEA 0(A4),A0
BSR CodeLWord
MOVE.L #$44894489,4(A4)
MOVE.L D2,D0
LEA 8(A4),A0
BSR CodeLWord
MOVEQ #3,D2
\EB1: MOVEQ #0,D0
BSR CodeLWord
DBRA D2,\EB1
LEA 8(A4),A0
MOVEQ #$28,D1
BSR TestSum
LEA $30(A4),A0
BSR CodeLWord
MOVE.L #$200,D0
MOVEA.L A2,A0
LEA $40(A4),A1
BSR CodeBlock
LEA $40(A4),A0
MOVE.W #$400,D1
BSR TestSum
LEA $38(A4),A0
BSR CodeLWord
MOVEM.L (A7)+,D2/A2/A4
RTS
;code Data Block
;>= D0 = Length of the Source
;>= A0 = Pointer to Source
;>= A1 = Pointer to Destination
CodeBlock:
movem.l d2/a5,-(a7)
MOVE.W D0,D1
LSL.W #2,D1
ORI.W #8,D1
MOVE.W D1,D2
movem.l d0-d1/a0-a1/a5,-(a7)
move.l a0,d1
move.l a1,a5
lea $dff000,a0
bsr BlitWait
bsr BlitterCode
movem.l (a7)+,d0-d1/a0-a1/a5
MOVE.L D0,D1
MOVEA.L A1,A0
BSR SetBorders
ADDA.L D1,A0
BSR SetBorders
ADDA.L D1,A0
BSR SetBorders
movem.l (a7)+,d2/a5
RTS
;A0 = $dff000
;D0 = Length of Source
;D1 = Source
;A5 = Destination
BlitterCode:
bsr Modulu ;set Mode
MOVE.L D1,$4C(A0)
MOVE.L D1,$50(A0)
MOVE.L A5,$54(A0)
MOVE.W #$1DB1,$40(A0)
MOVE.W #0,$42(A0)
bsr StartBlit
MOVE.L A5,$4C(A0) ;Source B
MOVE.L D1,$50(A0) ;Source A
MOVE.L A5,$54(A0) ;Dest
MOVE.W #$2d8c,$40(A0)
bsr StartBlit
movem.l d0-d1/a5,-(a7)
ADD.L D0,D1
SUBQ.L #2,D1
ADDA.L D0,A5
ADDA.L D0,A5
SUBQ.L #2,A5
MOVE.L D1,$4C(A0)
MOVE.L D1,$50(A0)
MOVE.L A5,$54(A0)
MOVE.W #$DB1,$40(A0)
MOVE.W #$1002,$42(A0)
bsr StartBlit
movem.l (a7)+,d0-d1/a5
movem.l d0-d1/a5,-(a7)
ADDA.L D0,A5
MOVE.L A5,$4C(A0)
MOVE.L D1,$50(A0)
MOVE.L A5,$54(A0)
MOVE.W #$1D8C,$40(A0)
MOVE.W #0,$42(A0)
bsr StartBlit
movem.l (a7)+,d0-d1/a5
rts
;start Blitter and wait for end of Blitter
StartBlit:
MOVE.W d2,$dff058
BlitWait: btst #14,$dff002
bne.s BlitWait
rts
;set Mode for coding
;>= A0 = $dff000
Modulu:
movem.l d0/a1,-(a7)
MOVEQ #0,D0
LEA $44(A0),A1
MOVE.L #-1,(A1)
LEA $62(A0),A1
MOVE.L D0,(A1)+
MOVE.W D0,(A1)+
ADDQ.L #8,A1
MOVE.W #$5555,(A1)
movem.l (a7)+,d0/a1
rts
;erase Track with DOS
;>= A0 = Pointer to Track-Buffer
DOSClear:
move.l #$444F5300,d0 ;DOS + 0
move.w #$57f,d1
\DO1: move.l d0,(a0)+ ;erase Track
addq.b #1,d0
dbf d1,\DO1
rts
;shorten Track and store in memory
;>= A0 = Pointer to beginning of Track
;>= A1 = Pointer to destination address
;>= Length = number of Bytes to be shortened
;>= ShrtByte = Byte, which should be stored shorter
;=> A1 = Pointer to memory for shortened Block
Crunch:
movem.l d2-d7/a2/a4,-(a7)
clr.w d7
clr.w d2
move.w Length,d3 ;number of Bytes
move.l MemoryLength,d6
\CHAnf:
tst.w d7
bne \CHEnd
movea.l a0,a2 ;intermediate storage for Address
\CH4: bsr \EraseBlock
tst.w d0
beq \CHAnf
move.b (a0),d4
cmp.b ShrtByte,d4
beq \KF1 ;Null byte
cmp.b 1(a0),d4
bne \CH10 ;no sequel
cmp.b 2(a0),d4
beq \AF1 ;other sequels
\CH10: addq.l #1,a0
subq.w #1,d3
bne \CH4 ;continue search
bsr \NoResult
\CHEnd:
move.b #$00,d0
move.b d0,(a1)+
subq.l #1,d6
bcs CrunEnd
move.l d6,MemoryLength
move.l a1,MemoryBeg
clr.l d0
movem.l (a7)+,d2-d7/a2/a4
rts
;short sequel
\KF1: cmp.b 1(a0),d4
bne \CH10 ;no Null
bsr \NoResult
bsr CounterBytes
cmp.w #$40,d1
bcc \KF2 ;too large for a Byte
ori.b #ShrtNull,d1
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
bra \KF4
\KF2: cmp.w #$1000,d1
bcc \KF3 ;too large, must be Word
move.w d1,d0
lsr.w #8,d0
ori.b #MiddleNull,d0 ;Null sequence with Byte
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
bra \KF4
\KF3: move.b #LongNull,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.w d1,d0
lsr.w #8,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
\KF4: bra \CHAnf
;other sequence
\AF1: bsr \NoResult
bsr CounterBytes
cmp.w #$40,d1
bcc \AF2 ;too large for a Byte
ori.b #ShrtNorm,d1
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
bra \AF4
\AF2: cmp.w #$1000,d1
bcc \AF3 ;too large, must be Word
move.w d1,d0
lsr.w #8,d0
ori.b #MiddleNorm,d0 ;any sequence
;Byte
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
bra \AF4
\AF3: move.b #LongNorm,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.w d1,d0
lsr.w #8,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd
\AF4: move.b d4,d0 ;store other Byte
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd
bra \CHAnf
;found no sequence
\NoResult2: move.w #1,Subtr ;See CrunEnd2
bra \KF20
\NoResult: clr.w Subtr
\KF20: move.l a0,a4
sub.l a2,a4
move.w a4,d1
beq \KFEnd
swap d1
move.w a4,d1
cmp.w #$40,d1
bcc \CH5 ;too large for a Byte
ori.b #ShrtNone,d1
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd2
bra \CH6
\CH5: cmp.w #$1000,d1
bcc \CH7 ;too large, must be Word
move.w d1,d0
lsr.w #8,d0
ori.b #MiddleNone,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd2
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd2
bra \CH6
\CH7: move.b #LongNone,D0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd2
move.w d1,d0
lsr.w #8,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd2
move.b d1,(a1)+
subq.l #1,d6
beq CrunEnd2
\CH6: swap d1
andi.l #$ffff,d1
sub.l d1,d6
beq CrunEnd2
bcs CrunEnd2
bra \CH8
\CH9: move.b (a2)+,(a1)+
\CH8: dbf d1,\CH9
\KFEnd: clr.w Subtr ;See CrunEnd2
rts
\EraseBlock:
move.w d3,d0
andi.w #$fe00,d0
cmp.w d0,d3
bne \LBEnd2
move.l a0,a3
move.w #$7e,d5
move.l (a0)+,d4
move.l d4,d0
andi.l #$ff000000,d0
cmp.l #$44000000,d0
bne \LBNone
\LB1: addq.b #1,d4
cmp.l (a0)+,d4
bne \LBNone
dbf d5,\LB1
bsr \NoResult2
move.b #EmptyBlock,d0
move.b d0,(a1)+
subq.l #1,d6
beq CrunEnd2
clr.w d0 ;Ok-Message
subi.w #$200,d3
bne \LBEnd
move.w #-1,d7 ;End mark
bra \LBEnd
\LBNone: move.l a3,a0
\LBEnd2: move.w #-1,d0
\LBEnd: rts
CounterBytes: clr.w d1
\ZB2: cmp.b (a0)+,d4
bne \ZB1
addq.w #1,d1
subq.w #1,d3
bne \ZB2
move.w #-1,d7 ;End mark
\ZB1:
subq.l #1,a0
rts
CrunEnd2: move.w Subtr,d2
\CE1: adda.l #$4,a7
dbf d2,\CE1
CrunEnd:
movem.l (a7)+,d2-d7/a2/a4
move.l #-1,d0
rts
;bring Track to normal size
;>= A0 = Pointer to crunched Track
;>= A1 = Pointer to destination address
DeCrunch:
move.b (a0)+,d0
tst.b d0
beq \DCEnd ;End mark
move.b d0,d1
andi.b #$c0,d1
bne Shrt
move.b d0,d1
andi.b #$30,d1
bne Middle
move.b d0,d1
cmpi.b #EmptyBlock,d1
beq \BlockClear
move.b (a0)+,d0
lsl.w #8,d0
move.b (a0)+,d0
cmpi.b #LongNull,d1
beq \NullLong
cmpi.b #LongNorm,d1
beq \NormLong
cmpi.b #LongNone,d1
beq \UndefLong
;error
move.l $4,a6
sub.l a5,a5
move.l #$12345678,d7
jsr -108(a6)
\DCEnd: rts
;empty Block
\BlockClear: move.w #$7f,d1
move.l #$444F5300,d0
\LB1: move.l d0,(a1)+
addq.b #1,d0
dbf d1,\LB1
bra DeCrunch
;Long
\LA1: move.b (a0)+,(a1)+
\UndefLong: dbf d0,\LA1
bra DeCrunch
\NullLong: move.b Shrtbyte,d1
bra \LA2
\NormLong: move.b (a0)+,d1
bra \LA2
\LA3: move.b d1,(a1)+
\LA2: dbf d0,\LA3
bra DeCrunch
Shrt:
cmpi.b #ShrtNull,d1
beq \KU1
cmpi.b #ShrtNorm,d1
beq \KU2
;ShrtUndeff
andi.w #$3f,d0
bra \KU3
\KU4: move.b (a0)+,(a1)+
\KU3: dbf d0,\KU4
bra DeCrunch
\KU1: move.b Shrtbyte,d1
bra \KU5
\KU2: move.b (a0)+,d1
\KU5: andi.w #$003f,d0
bra \KU6
\KU7: move.b d1,(a1)+
\KU6: dbf d0,\Ku7
bra DeCrunch
Middle:
andi.w #$0f,d0
lsl.w #8,d0
move.b (a0)+,d0
cmpi.b #MiddleNull,d1
beq \KU1
cmpi.b #MiddleNorm,d1
beq \KU2
;MiddleUndeff
bra \KU3
\KU4: move.b (a0)+,(a1)+
\KU3: dbf d0,\KU4
bra DeCrunch
\KU1: move.b Shrtbyte,d1
bra \KU6
\KU2: move.b (a0)+,d1
bra \KU6
\KU7: move.b d1,(a1)+
\KU6: dbf d0,\Ku7
bra DeCrunch
beg:
move.w #$0008,$dff09a
move.l gfxbase,a6
lea bitmap,a0
move.b #1,d0
move.w #320,d1
move.w #200,d2 ;PAL uses 256
jsr InitBitMap(a6)
move.l bit_adress,plane1
move.l bit_adress,d1
move.w d1,plane_lo
swap d1
move.w d1,plane_hi
lea rastport,a1
jsr InitRastPort(a6)
move.l #bitmap,r_bitmap
move.l #ncopper,a0
move.l cop_adress,a1
move.l #copsize,d0
copy_loop:
move.b (a0)+,(a1)+
dbf d0,copy_loop
bsr adresses
move.l c1_adress,flash_adress
move.l bit_adress,a0
move.w #$27ff,d0
clear_loop:
clr.b (a0)+
dbf d0,clear_loop
move.l gfxbase,a0
move.w #$0080,$dff096
move.l $6c,oldirq
move.l #newirq,$6c
move.l 50(a0),oldcopper
move.l cop_adress,50(a0)
move.w #$82b0,$dff096
new_start:
move.w #7,x1
move.w #54,y1
move.b #$4f,lc
move.b #$00,fc
move.b #$03,tr
move.b #$00,ws
move.b #$01,vd
move.b #$01,fa
move.b #$00,dc1
move.b #$00,dc2
move.b #$01,sd
move.b #$00,dd
move.b #$01,sy
move.b #$00,new
move.b #$00,pointer1
move.b #$00,color_ptr
move.b drives,dd
bsr end_drive
bsr show_lc
move.l #text1,text_ptr
bsr set_title
bra menu_control
exit:
move.w #$8008,$dff09a
move.l gfxbase,a0
move.w #$0080,$dff096
move.l oldirq,$6c
move.l oldcopper,50(a0)
move.w #$82b0,$dff096
no_DPuffer:
move.l ExecBase,a6
move.l cop_adress,a1
move.l #copsize+2,d0
jsr FreeMem(a6)
no_copper:
move.l ExecBase,a6
move.l bit_adress,a1
move.l #$2800,d0
jsr FreeMem(a6)
no_bitmap:
move.l ExecBase,a6
move.l gfxbase,a1
jsr CloseLibrary(a6)
no_gfxbase:
clr.l d0
rts
newirq:
move SR,-(a7)
movem.l a0-a6/d0-d7,-(a7)
addq.b #1,waiting
cmp.b #2,waiting
ble endirq
clr.b waiting
move.l flash_adress,a2
cmpi.b #$00,color_ptr
bne.s irq_flash
move.w #$00ee,(a2)
bra.s endirq
irq_flash:
cmpi.b #$00,back
beq.s upward
downward:
subi.w #$0011,(a2)
cmpi.w #$0044,(a2)
bcc.s endirq
move.b #$00,back
bra.s endirq
upward: addi.w #$0011,(a2)
cmpi.w #$00ff,(a2)
bcs.s endirq
move.b #$01,back
endirq: movem.l (a7)+,a0-a6/d0-d7
move (a7)+,SR
dc.w $4ef9
oldirq: dc.l 0
menu_control:
bsr wait_key
cmpi.b #$46,d0
beq destination_drive
cmpi.b #$50,d0
beq start_copy
cmpi.b #$51,d0
beq first_cylinder
cmpi.b #$52,d0
beq last_cylinder
cmpi.b #$53,d0
beq how_many_tries
cmpi.b #$54,d0
beq write_serveral_times
cmpi.b #$55,d0
beq verify_destination
cmpi.b #$56,d0
beq fast_copy
cmpi.b #$57,d0
beq deepcopy_1
cmpi.b #$58,d0
beq deepcopy_2
cmpi.b #$59,d0
beq source_drive
cmpi.b #$21,d0
beq synccorrection
bra.s menu_control
start_copy:
move.l c2_adress,flash_adress
move.b #$01,color_ptr
bsr show_start
start_copy2:
bsr wait_key
cmpi.b #$45,d0
beq new_start
cmpi.b #$44,d0 ;Return
beq.s end_start
cmpi.b #$43,d0
bne.s start_copy2
end_start:
move.b #$00,color_ptr
move.w #28,y1
bsr cl2
move.w #10,d0
estlop: bsr Timer
dbf d0,estlop
bsr clear_eol
bsr copy_start ;Copy-Routine
cmp.w #Escape,ErrorFlag
beq new_start
cmp.w #diskprotect,errorflag
beq start_copy
cmp.w #NoDisk,errorflag
beq start_copy
cmp.w #NotProtect,ErrorFlag
beq.s start_copy
bsr cl1
esd1: bsr wait_key
cmpi.b #$40,d0
bne.s esd1
esd2: bra new_start
destination_drive:
move.l c13_adress,flash_adress
move.b #$01,color_ptr
destination1:
bsr wait_key
cmpi.b #$0a,d0
beq.s d_drive0
cmpi.b #$01,d0
beq.s d_drive1
cmpi.b #$02,d0
beq d_drive2
cmpi.b #$03,d0
beq d_drive3
cmpi.b #$43,d0
beq.s end_destination
cmpi.b #$44,d0
bne.s destination1
end_destination:
cmpi.b #$00,dd
beq.s destination1
move.b #$00,color_ptr
bra menu_control
d_drive0:
btst #0,drives
beq end_drive
btst #0,dd
beq.s dd0_0
bclr #0,dd
bra.s dd0_1
dd0_0: bset #0,dd
move.b #1,drv
dd0_1: bra end_drive
d_drive1:
btst #1,drives
beq end_drive
btst #1,dd
beq.s dd1_0
bclr #1,dd
bra.s dd1_1
dd1_0: bset #1,dd
move.b #2,drv
dd1_1: bra.s end_drive
d_drive2:
btst #2,drives
beq.s end_drive
btst #2,dd
beq.s dd2_0
bclr #2,dd
bra.s dd2_1
dd2_0: bset #2,dd
move.b #4,drv
dd2_1: bra.s end_drive
d_drive3:
btst #3,drives
beq.s end_drive
btst #3,dd
beq.s dd3_0
bclr #3,dd
bra.s end_drive
dd3_0: bset #3,dd
move.b #8,drv
end_drive:
cmpi.b #$01,dc1
bne.s st1
bra.s st2
st1: cmpi.b #$01,dc2
bne steve1
st2: move.b drv,dd
bra steve
steve1: btst #0,sd
beq.s ste1
andi.b #$0e,dd
cmpi.b #$00,dd
bne.s steve
bset #0,dd
bra.s steve
ste1: btst #1,sd
beq.s ste2
andi.b #$0d,dd
cmpi.b #$00,dd
bne.s steve
bset #1,dd
bra.s steve
ste2: btst #2,sd
beq.s ste3
andi.b #$0b,dd
cmpi.b #$00,dd
bne.s steve
bset #2,dd
bra.s steve
ste3: btst #3,sd
beq.s steve
andi.b #$07,dd
cmpi.b #$00,dd
bne.s steve
bset #3,dd
steve: btst #0,dd
bne.s end_dd1
lea off_text,a0
bra.s end_dd2
end_dd1:lea on_text2,a0
end_dd2:bsr set_drive0
btst #1,dd
bne.s end_dd3
lea off_text,a0
bra.s end_dd4
end_dd3:lea on_text2,a0
end_dd4:bsr set_drive1
btst #2,dd
bne.s end_dd5
lea off_text,a0
bra.s end_dd6
end_dd5:lea on_text2,a0
end_dd6:bsr set_drive2
btst #3,dd
bne.s end_dd7
lea off_text,a0
bra.s end_dd8
end_dd7:lea on_text2,a0
end_dd8:bsr set_drive3
cmpi.b #$00,pointer1
bne.s end_dd9
move.b #$01,pointer1
rts
end_dd9:bra destination1
set_drive0:
move.l gfxbase,a6
lea rastport,a1
move.w #61,d0
move.w #190,d1 ;PAL 213
jsr Movee(a6)
bra.s set_text
set_drive1:
move.l gfxbase,a6
lea rastport,a1
move.w #126,d0
move.w #190,d1 ;PAL 213
jsr Movee(a6)
bra.s set_text
set_drive2:
move.l gfxbase,a6
lea rastport,a1
move.w #190,d0
move.w #190,d1 ;PAL 213
jsr Movee(a6)
bra.s set_text
set_drive3:
move.l gfxbase,a6
lea rastport,a1
move.w #254,d0
move.w #190,d1 ;PAL 213
jsr Movee(a6)
set_text:
lea rastport,a1
move.w #$0003,d0
jsr Textout(a6)
rts
first_cylinder:
move.l c3_adress,flash_adress
move.b #$01,color_ptr
bsr wait_key
cmpi.b #$4f,d0
beq.s fc_down
cmpi.b #$4e,d0
beq.s fc_up
cmpi.b #$43,d0
beq compare_fc
cmpi.b #$44,d0
bne.s first_cylinder
compare_fc:
move.b lc,d0
cmp.b fc,d0
beq compare_fc2
blt.s first_cylinder
compare_fc2:
move.b #$00,color_ptr
bra menu_control
fc_down:subi.b #$01,fc
cmpi.b #$ff,fc
bne.s fc_down2
move.b #$00,fc
fc_down2:
bra show_fc
fc_up: addi.b #$01,fc
cmpi.b #$52,fc
bne.s fc_down2
move.b #$51,fc
show_fc:lea fc_text,a0
move.b fc,d0
bsr byte_calculate
move.l gfxbase,a6
lea rastport,a1
move.w #295,d0
move.w #64,d1
jsr Movee(a6)
lea rastport,a1
lea fc_text,a0
move.w #$0002,d0
jsr Textout(a6)
bra first_cylinder
last_cylinder:
move.l c4_adress,flash_adress
move.b #$01,color_ptr
bsr wait_key
cmpi.b #$4f,d0
beq.s lc_down
cmpi.b #$4e,d0
beq.s lc_up
cmpi.b #$43,d0
beq compare_lc
cmpi.b #$44,d0
bne.s last_cylinder
compare_lc:
move.b fc,d0
cmp.b lc,d0
beq compare_lc2
bge.s last_cylinder
compare_lc2:
move.b #$00,color_ptr
bra menu_control
lc_down:subi.b #$01,lc
cmpi.b #$ff,lc
bne.s lc_down2
move.b #$00,lc
lc_down2:
bra lcc
lc_up: addi.b #$01,lc
cmpi.b #$52,lc
bne.s lc_down2
move.b #$51,lc
lcc: bsr.s show_lc
bra last_cylinder
show_lc:lea lc_text,a0
move.b lc,d0
bsr byte_calculate
move.l gfxbase,a6
lea rastport,a1
move.w #295,d0
move.w #74,d1
jsr Movee(a6)
lea rastport,a1
lea lc_text,a0
move.w #$0002,d0
jsr Textout(a6)
rts
how_many_tries:
move.l c5_adress,flash_adress
move.b #$01,color_ptr
tries1: lea tr_text,a0
bsr wait_key
cmpi.b #$4e,d0
beq.s tries_up
cmpi.b #$4f,d0
beq.s tries_down
cmpi.b #$43,d0
beq.s end_tries
cmpi.b #$44,d0
bne.s tries1
end_tries:
move.b #$00,color_ptr
bra menu_control
tries_up:
addi.b #$01,tr
cmpi.b #$0a,tr
bne.s tries_up2
move.b #$09,tr
tries_up2:
move.b tr,d0
addi.w #$30,d0
move.b d0,(a0)
bra.s tries2
tries_down:
subi.b #$01,tr
cmpi.b #$00,tr
bne.s tries_down2
move.b #$01,tr
tries_down2:
move.b tr,d0
addi.w #$30,d0
move.b d0,(a0)
tries2: move.l gfxbase,a6
lea rastport,a1
move.w #303,d0
move.w #84,d1
jsr Movee(a6)
lea rastport,a1
lea tr_text,a0
move.w #$0001,d0
jsr Textout(a6)
bra tries1
synccorrection:
move.l c12_adress,flash_adress
move.b #$01,color_ptr
cmpi.b #$01,sy
bne.s sync2
clr.b sy
lea off_text,a0
bra.s sync3
sync2: move.b #$01,sy
lea on_text,a0
sync3: lea rastport,a1
move.w #287,d0
move.w #157,d1
jsr Movee(a6)
lea rastport,a1
move.w #3,d0
jsr Textout(a6)
move.b #$00,color_ptr
bra menu_control
write_serveral_times:
move.l c6_adress,flash_adress
move.b #$01,color_ptr
move.b sd,d0
cmp.b dd,d0
bne wait_return
cmpi.b #$00,ws
bne.s write_s2
write_s1:
move.b #$01,ws
lea on_text,a0
bra.s end_write_serveral
write_s2:
move.b #$00,ws
lea off_text,a0
end_write_serveral:
move.l gfxbase,a6
lea rastport,a1
move.w #287,d0
move.w #94,d1
jsr Movee(a6)
lea rastport,a1
move.w #$0003,d0
jsr Textout(a6)
esw: move.b #$00,color_ptr
bra menu_control
verify_destination:
move.b dc1,d0
or.b dc2,d0
tst.b d0
bne menu_control
move.l c7_adress,flash_adress
move.b #$01,color_ptr
cmpi.b #$00,vd
bne.s verify_d2
verify_d1:
move.b #$01,vd
lea on_text,a0
bra.s end_verify
verify_d2:
move.b #$00,vd
lea off_text,a0
end_verify:
bsr verify_d3
bra menu_control
verify_off:
move.b #$00,vd
lea off_text,a0
verify_d3:
move.l gfxbase,a6
lea rastport,a1
move.w #287,d0
move.w #104,d1
jsr Movee(a6)
lea rastport,a1
move.w #$0003,d0
jsr Textout(a6)
move.b #$00,color_ptr
rts
fast_copy:
move.l c8_adress,flash_adress
move.b #$01,color_ptr
cmpi.b #$01,dd
beq.s fcop1
cmpi.b #$02,dd
beq.s fcop1
cmpi.b #$04,dd
beq.s fcop1
cmpi.b #$08,dd
beq.s fcop1
bra wait_return
fcop1: cmpi.b #$01,fa
bne.s fastcopy1
move.b #$00,fa
move.b #$01,dc1
move.b #$00,dc2
bra.s end_fast
fastcopy1:
move.b #$01,fa
move.b #$00,dc1
move.b #$00,dc2
end_fast:
cmp.b #ON,DC1
bne fcop2
bsr verify_off
fcop2: bsr show_copies
move.b #$00,color_ptr
bra menu_control
deepcopy_1:
bsr verify_off
move.l c9_adress,flash_adress
move.b #$01,color_ptr
cmpi.b #$01,dd
beq.s deep4
cmpi.b #$02,dd
beq.s deep4
cmpi.b #$04,dd
beq.s deep4
cmpi.b #$08,dd
beq.s deep4
bra.s wait_return
deep4: cmpi.b #$00,dc1
beq.s deep1
move.b #$00,fa
move.b #$00,dc1
move.b #$01,dc2
bra.s end_deep1
deep1: move.b #$00,fa
move.b #$01,dc1
move.b #$00,dc2
end_deep1:
bra end_fast
wait_return:
move.l #text12,text_ptr
move.w #16,x1
move.w #28,y1
bsr set_text3
wait_r3:bsr wait_key
cmpi.b #$44,d0
beq.s wait_r2
cmpi.b #$43,d0
bne.s wait_return
wait_r2:
bsr BegText
bra end_fast
wait_r4:bsr wait_key
cmpi.b #$45,d0
beq.s wait_r5
cmpi.b #$44,d0
beq \W1
cmpi.b #$43,d0
beq \W1
cmpi.b #$40,d0
bne.s wait_r4
\W1: move.l d0,-(a7)
bsr clear_eol
move.l (a7)+,d0
clr.l d0
rts
wait_r5:move.l #-1,d0
move.w #Escape,ErrorFlag
rts
deepcopy_2:
bsr verify_off
move.l c10_adress,flash_adress
move.b #$01,color_ptr
cmpi.b #$01,dd
beq.s deep3
cmpi.b #$02,dd
beq.s deep3
cmpi.b #$04,dd
beq.s deep3
cmpi.b #$08,dd
beq.s deep3
bra wait_return
deep3: cmpi.b #$01,dc2
beq.s deep2
move.b #$00,fa
move.b #$00,dc1
move.b #$01,dc2
bra.s end_deep2
deep2: move.b #$01,fa
move.b #$00,dc1
move.b #$00,dc2
end_deep2:
bra end_fast
show_copies:
move.l gfxbase,a6
lea rastport,a1
move.w #287,d0
move.w #114,d1
jsr Movee(a6)
lea rastport,a1
cmpi.b #$00,fa
beq.s show1
lea on_text,a0
bra.s show2
show1: lea off_text,a0
show2: move.w #$0003,d0
jsr Textout(a6)
lea rastport,a1
move.w #287,d0
move.w #124,d1
jsr Movee(a6)
lea rastport,a1
cmpi.b #$00,dc1
beq.s show3
lea on_text,a0
bra.s show4
show3: lea off_text,a0
show4: move.w #$0003,d0
jsr Textout(a6)
lea rastport,a1
move.w #287,d0
move.w #134,d1
jsr Movee(a6)
lea rastport,a1
cmpi.b #$00,dc2
beq.s show5
lea on_text,a0
bra.s show6
show5: lea off_text,a0
show6: move.w #$0003,d0
jsr Textout(a6)
rts
source_drive:
move.l c11_adress,flash_adress
move.b #$01,color_ptr
source1:
bsr wait_key
cmpi.b #$0a,d0
beq.s s_drive0
cmpi.b #$01,d0
beq.s s_drive1
cmpi.b #$02,d0
beq s_drive2
cmpi.b #$03,d0
beq s_drive3
cmpi.b #$43,d0
beq.s source2
cmpi.b #$44,d0
bne.s source1
source2:move.b pointer1,d7
clr.b pointer1
bsr end_drive
move.b d7,pointer1
move.b #$00,color_ptr
bra menu_control
s_drive0:
btst #$00,drives
beq source1
s_dd0: move.b #$01,sd
move.b #$00,d0
bra set_s_drive
s_drive1:
btst #$01,drives
beq source1
s_dd1: move.b #$02,sd
move.b #$01,d0
bra set_s_drive
s_drive2:
btst #$02,drives
beq source1
s_dd2: move.b #$04,sd
move.b #$02,d0
bra.s set_s_drive
s_drive3:
btst #$03,drives
beq source1
move.b #$08,sd
s_dd3: move.b #$03,d0
set_s_drive:
lea sd_text,a0
addi.b #$30,d0
move.b d0,(a0)
move.l gfxbase,a6
lea rastport,a1
move.w #303,d0
move.w #144,d1
jsr movee(a6)
lea rastport,a1
move.w #$0001,d0
jsr Textout(a6)
bra source1
byte_calculate:
cmpi.w #$0a,d0
bmi.s byte2
divu #$0a,d0
move.w d0,d1
addi.w #$30,d1
swap d0
bra.s byte3
byte2: move.w #$0030,d1
byte3: move.b d1,(a0)+
addi.w #$0030,d0
move.b d0,(a0)+
rts
adresses:
move.l cop_adress,d0
move.l #color1,d1
move.l #ncopper,d2
sub.l d2,d1
add.l d1,d0
move.l d0,c1_adress
addi.l #$000010,d0
move.l d0,c2_adress
addi.l #$000008,d0
move.l d0,c3_adress
addi.l #$000008,d0
move.l d0,c4_adress
addi.l #$000008,d0
move.l d0,c5_adress
addi.l #$000008,d0
move.l d0,c6_adress
addi.l #$000008,d0
move.l d0,c7_adress
addi.l #$000008,d0
move.l d0,c8_adress
addi.l #$000008,d0
move.l d0,c9_adress
addi.l #$000008,d0
move.l d0,c10_adress
addi.l #$000008,d0
move.l d0,c11_adress
addi.l #$000008,d0
move.l d0,c12_adress
addi.l #$000010,d0
move.l d0,c13_adress
rts
set_title:
clr.l d6
move.w #$0009,d6
set_text1:
move.l gfxbase,a6
bsr set_text2
addi.l #$000026,text_ptr
addi.w #$000a,y1
dbf d6,set_text1
lea floppy,a0
move.l bit_adress,a1
add.l #$001c26,a1
move.l a1,a2
bsr.s box
lea floppy,a0
move.l a1,a2
add.l #$000008,a2
bsr.s box
lea floppy,a0
move.l a1,a2
add.l #$000010,a2
bsr.s box
lea floppy,a0
move.l a1,a2
add.l #$000018,a2
bsr.s box
bra.s set_work
box: rts ;Remove this rts for PAL systems
move.w #floppy_s,d0 ;will draw graphic disk drive onscreen
bit_copy_loop:
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+
move.b (a0)+,(a2)+
add.l #$22,a2
dbf d0,bit_copy_loop
rts
set_work:
move.w #44,y2
bsr draw_line
move.w #148,y2
bsr draw_line
move.w #218,y2
bsr draw_line
move.w #250,y2
bsr draw_line
move.w #160,y2
bsr draw_line
move.w #157,y1
move.l #text11,text_ptr
bsr set_text2
move.w #170,y1
move.w #$0001,d2
move.l #text2,text_ptr
set_loop2:
bsr set_text2
addi.l #$000026,text_ptr
addi.w #$000a,y1
dbf d2,set_loop2
move.w #$0001,d2
move.l #text3,text_ptr
move.w #200,y1 ;PAL uses 230
bsr set_text2; ;added to NTSC
move.l #text3a,text_ptr ;added to NTSC
move.w #7,x1 ;to position text
move.w #210,y1 ;PAL uses 245
set_loop3:
bsr set_text2
addi.w #$000f,y1
addi.l #$000026,text_ptr
dbf d2,set_loop3
lea rastport,a1
move.b #1,d0
jsr SetAPen(a6)
lea rastport,a1
move.w #10,d0
move.w #10,d1
move.w #309,d2
move.w #40,d3
jsr RectFill(a6)
lea rastport,a1
move.b #0,d0
jsr SetAPen(a6)
lea rastport,a1
move.w #11,d0
move.w #11,d1
move.w #308,d2
move.w #39,d3
jsr RectFill(a6)
lea rastport,a1
move.b #1,d0
jsr SetAPen(a6)
BegText: move.l #text4,text_ptr
move.w #16,x1
move.w #18,y1
bsr set_text3
move.l #text20,text_ptr
move.w #28,y1
bsr set_text3
move.l #text21,text_ptr
move.w #38,y1
bsr set_text3
rts
draw_line:
lea rastport,a1
move.w #$0000,d0
move.w y2,d1
jsr Movee(a6)
lea rastport,a1
move.w #$013f,d0
move.w y2,d1
jsr Draw(a6)
rts
set_text2:
move.l a6,-(a7)
move.l gfxbase,a6
lea rastport,a1
move.w x1,d0
move.w y1,d1
jsr Movee(a6)
lea rastport,a1
move.l text_ptr,a0
move.w #$0026,d0
jsr Textout(a6)
move.l (a7)+,a6
rts
set_text3:
move.l a6,-(a7)
move.l gfxbase,a6
lea rastport,a1
move.w x1,d0
move.w y1,d1
jsr Movee(a6)
lea rastport,a1
move.l text_ptr,a0
move.w #$0024,d0
jsr Textout(a6)
move.l (a7)+,a6
rts
show_start:
lea text6,a0
btst #0,dd
bne show_s1
btst #0,sd
beq.s show_start1
show_s1:lea df0,a1
bsr copy_drives
show_start1:
btst #1,dd
bne.s show_s2
btst #1,sd
beq.s show_start2
show_s2:lea df1,a1
bsr copy_drives
show_start2:
btst #2,dd
bne.s show_s3
btst #2,sd
beq.s show_start3
show_s3:lea df2,a1
bsr.s copy_drives
show_start3:
btst #3,dd
bne.s show_s4
btst #3,sd
beq.s show_start4
show_s4:lea df3,a1
bsr.s copy_drives
show_start4:
move.w #16,x1
move.w #18,y1
move.w #$002,d2
move.l #text5,text_ptr
show_loop:
bsr set_text3
addi.w #$000a,y1
addi.l #$000024,text_ptr
dbf d2,show_loop
move.w #16,d0
lea text6,a0
lop: move.b #$20,(a0)+
dbf d0,lop
rts
copy_drives:
move.w #$0003,d0
copy_d_loop:
move.b (a1)+,(a0)+
dbf d0,copy_d_loop
rts
read_error:
clr.l d0
move.b cylinder,d0
lea text7,a0
add.l #$00001a,a0
bsr byte_calculate
move.b side,d0
add.l #$000006,a0
bsr byte_calculate
move.w #7,x1
move.w #200,y1 ;PAL uses 230
move.l #text7,text_ptr
bra set_text2
write_error:
clr.l d0
move.b cylinder,d0
lea text8,a0
add.l #$00001b,a0
bsr byte_calculate
move.b side,d0
add.l #$000006,a0
bsr byte_calculate
move.w #7,x1
move.w #200,y1 ;PAL uses 230
move.l #text8,text_ptr
bra set_text2
clear_error:
move.l #text3,text_ptr
move.w #7,x1
move.w #200,y1 ;PAL uses 230
bra set_text2
move.l #text3a,text_ptr ;added to NTSC
move.w #7,x1 ;to position text
move.w #210,y1 ;(PAL uses 245)
bra set_text2 ;on the screen
reading_cyl:
clr.l d0
move.b cylinder,d0
lea rcyl_text,a0
bsr byte_calculate
lea rcyl_text,a0
move.l gfxbase,a6
lea rastport,a1
move.w #127,d0
move.w #210,d1 ;PALS uses 245
jsr Movee(a6)
lea rastport,a1
move.w #$0002,d0
jsr Textout(a6)
rts
writing_cyl:
clr.l d0
move.b cylinder,d0
lea wcyl_text,a0
bsr byte_calculate
lea wcyl_text,a0
move.l gfxbase,a6
lea rastport,a1
move.w #271,d0
move.w #210,d1 ;PAL uses 245
jsr Movee(a6)
lea rastport,a1
move.w #$0002,d0
jsr Textout(a6)
rts
insert_source:
move.l #text9,text_ptr
bra.s melvin
insert_destination:
move.l #text10,text_ptr
bra.s melvin
protect_source:
bsr cl
move.l #text13,text_ptr
bra.s melvin
protect_destination:
bsr cl
move.l #text14,text_ptr
melvin:
move.w #16,x1
move.w #28,y1
bsr set_text3
move.l #text5,text_ptr
move.w #18,y1
bsr set_text3
bra wait_r4
clear_eol:
move.l #text15,text_ptr
move.w #16,x1
move.w #28,y1
bsr set_text3
move.w #18,y1
bra set_text3
write_b_again:
bsr cl
move.l #text17,text_ptr
move.w #16,x1
move.w #28,y1
bsr set_text3
wba1: bsr wait_key
cmpi.b #$45,d0 ;check esc
beq.s wba4
cmpi.b #$15,d0 ;German keyboards use 31 y and z reversed
beq.s wba2
cmpi.b #$36,d0 ;check n
bne.s wba1
move.l #-1,d0
bra.s wba3
wba2: clr.l d0
wba3: move.l d0,-(a7)
bsr clear_eol
move.l (a7)+,d0
rts
wba4: move.w #escape,errorflag
rts
compare_drives:
move.w #18,y1
bsr cl2
lea text19,a0
clr.w d2
cdl1: lea df0,a1
btst d2,vererrflag
beq.s cdl4
move.w d2,d0
lsl #2,d0
add.l d0,a1
bsr.s cdl2
cdl4: addq.w #1,d2
cmpi.w #4,d2
bne.s cdl1
move.l #text18,text_ptr
move.w #28,y1
bra set_text3
cdl2: move.w #3,d1
cdl3: move.b (a1)+,(a0)+
dbf d1,cdl3
rts
wait_key:
movem.l d1-d7,-(a7)
move.w Keybrdclr,d1
l8: move.b IntCon,d0
btst #7,d1
bne l1
sub.l #1,Keybrdcnt
beq Keybrepeat
l1: btst #3,d0
beq l8
move.b Key,d0
ori.b #$40,Cont
not.b d0
ror.b #1,d0
move.w #$600,d1
l5: dbf d1,l5
andi.b #$bf,Cont
move.l #MaxWait,Cntwait
move.l #MaxWait,Keybrdcnt
move.w d0,Keybrdclr
Keybtdend:
movem.l (a7)+,d1-d7
rts
Keybrepeat:
move.l Cntwait,d1
cmp.l #MinWait,d1
bcs.s repeat1
sub.l #$800,d1
move.l d1,Cntwait
repeat1:move.l d1,Keybrdcnt
move.w Keybrdclr,d0
bra.s Keybtdend
get_key:
move.w $dff01e,d1
btst #3,d1
beq \l1
move.b Key,d0
ori.b #$40,Cont
not.b d0
ror.b #1,d0
move.w #$600,d1
\l2: dbf d1,\l2
andi.b #$bf,Cont
\l1: rts
cl: move.w #28,y1
cl2: move.w #16,x1
move.l #text15,text_ptr
bsr set_text3
addi.w #10,y1
bsr set_text3
rts
cl1: bsr.s cl
move.w #18,y1
bsr set_text3
move.w #28,y1
move.l #text16,text_ptr
bsr set_text3
rts
gfxname:
dc.b "graphics.library",0
align.w
gfxbase: dc.l 0
oldcopper: dc.l 0
bit_adress: dc.l 0
cop_adress: dc.l 0
c1_adress: dc.l 0
c2_adress: dc.l 0
c3_adress: dc.l 0
c4_adress: dc.l 0
c5_adress: dc.l 0
c6_adress: dc.l 0
c7_adress: dc.l 0
c8_adress: dc.l 0
c9_adress: dc.l 0
c10_adress: dc.l 0
c11_adress: dc.l 0
c12_adress: dc.l 0
c13_adress: dc.l 0
rastport: blk.l 1,0
r_bitmap: blk.l 24,0
bitmap: blk.l 2,0
plane1: blk.l 8,0
ncopper:
dc.w $008e,$2681,$0090,$24c1
dc.w $0092,$0038,$0094,$00d0
dc.w $00e0
plane_hi: dc.w $0000,$00e2
plane_lo: dc.w $0000
dc.w $0100,$1200,$0102,$0000,$0104,$0000
dc.w $0108,$0000,$010a,$0000
dc.w $0120,$0000,$0122,$0000
dc.w $0180,$0000,$0182
color1: dc.w $00ee,$0d01,$fffe,$0182
dc.w $00ee,$5401,$fffe,$0182
color2: dc.w $00ee,$6001,$fffe,$0182
color3: dc.w $00ee,$6a01,$fffe,$0182
color4: dc.w $00ee,$7201,$fffe,$0182
color5: dc.w $00ee,$7d01,$fffe,$0182
color6: dc.w $00ee,$8601,$fffe,$0182
color7: dc.w $00ee,$9001,$fffe,$0182
color8: dc.w $00ee,$9a01,$fffe,$0182
color9: dc.w $00ee,$a401,$fffe,$0182
color10: dc.w $00ee,$af01,$fffe,$0182
color11: dc.w $00ee,$b701,$fffe,$0182
color12: dc.w $00ee,$c501,$fffe,$0182
dc.w $00ee,$c701,$fffe,$0182
color13: dc.w $00ee,$ff01,$fffe,$0182
dc.w $00ee,$ffff,$fffe
dc.w $0000,$0000
copend:
copsize = copend - ncopper
drives: dc.b 0
d_drives: dc.b 0
s_drives: dc.b 0
color_ptr: dc.b 0
back: dc.b 0
pointer1: dc.b 0
cylinder: dc.b 0
side: dc.b 0
new: dc.b 0
drv: dc.b 0
align.w
flash_adress: dc.l 0
text_ptr: dc.l 0
x1: dc.w 7
y1: dc.w 54
y2: dc.w 0
keybrdclr: dc.w $ffff
cntwait: dc.l MaxWait
keybrdcnt: dc.l MaxWait
fc_text: dc.b "00"
ralf: dc.b 0
lc_text: dc.b "79"
tr_text: dc.b "0"
sd_text: dc.b "0"
rcyl_text: dc.b "00"
wcyl_text: dc.b "00"
on_text: dc.b ".ON"
on_text2: dc.b " ON"
off_text: dc.b "OFF"
df0: dc.b "DF0 "
df1: dc.b "DF1 "
df2: dc.b "DF2 "
df3: dc.b "DF3 "
text1: dc.b "F1 = START COPY......................"
dc.b "F2 = FIRST CYLINDER (CRSR).........00"
dc.b "F3 = LAST CYLINDER (CRSR).........79"
dc.b "F4 = HOW MANY TRIES (CRSR)..........3"
dc.b "F5 = WRITE SEVERAL TIMES..........OFF"
dc.b "F6 = VERIFY DESTINATION............ON"
dc.b "F7 = FASTCOPY......................ON"
dc.b "F8 = DEEPCOPY 1...................OFF"
dc.b "F9 = DEEPCOPY 2...................OFF"
dc.b "F10 = SOURCE DRIVE (0/1/2/3).......DF0"
text2: dc.b "DEL = DESTINATION DRIVE (0/1/2/3)....."
dc.b " DF0: DF1: DF2: DF3: "
text3: dc.b " STATUS: 00, OK,00,00 "
text3a: dc.b " READING CYL. 00 / WRITING CYL. 00 "
;text3a added for text positioning on NTSC systems
text4: dc.b " A M I G A - COPY V1.2 "
text5: dc.b " (ESC) TERMINATES COPY "
dc.b "INSERT DISK(S) IN "
text6: dc.b " "
dc.b "PRESS RETURN OR ENTER WHEN READY !¡!"
text7: dc.b "STATUS: READ-ERROR ON CYL.00 SIDE 00 "
text8: dc.b "STATUS: WRITE-ERROR ON CYL.00 SIDE 00 "
text9: dc.b " PLEASE INSERT SOURCE DISK !! "
text10: dc.b " PLEASE INSERT DESTINATION DISK ! "
text11: dc.b " S = SYNC-CORRECTION... ..........ON"
text12: dc.b " ONLY ONE DESTINATION !! "
text13: dc.b " SOURCE DISK INSN'T WRITE PROTECTED."
text14: dc.b "DESTINATION DISK IS WRITE PROTECTED."
text15: dc.b " "
text16: dc.b " COPY COMPLETE !! "
text17: dc.b " WRITE BUFFER AGAIN ??? (Y/N) "
text18: dc.b " ERROR ON DRIVE(S) "
text19: dc.b " "
text20: dc.b " WRITTEN BY : "
text21: dc.b " R. GELFAND AND S. THUBEAUVILLE "
align.w
floppy:
dc.l $00000000,$00000000,$00000000,$00000000,$000007ff,$ffffffe0
dc.l $04000000,$002005ff,$ffffffa0,$05ffffff,$ffa00400,$00000020
dc.l $04ffffff,$ff200880,$00000110,$08800000,$01100880,$1ff80110
dc.l $08801008,$011008bf,$f00ffd10,$07a00000,$05e008bf,$f00ffd10
dc.l $08800ff0,$01100a90,$00000110,$08800000,$01100480,$00000120
dc.l $04ffffff,$ff200400,$00000020,$07ffffff,$ffe00000,$00000000
floppyend:
;graphic of disk drive not used by NTSC system
;Fast Copy
DecodeCnt: dc.w 0 ;Counter for longwords to be decoded
DecodeAdr: dc.l 0 ;Address where to decode
BlockAdr: dc.w 0 ;Offset in Block for decoding
FTestAdr: dc.l 0 ;Test address if Block already loaded
SectNum: dc.w 0 ;Counter for Sector number
BytesBefGap: dc.w 0 ;Bytes before the Gap
BytesAftGAp: dc.w 0 ;Bytes after the Gap
FirstBlock: dc.w 0 ;Block number of the first Block
FirstBlockSp: dc.w 0 ;permanent memory for first Block
SectBL: dc.w 0 ;Sector counter for Sectors before the Gap
VerifyFlag: dc.w 0 ;indicates if read or Verify
VerErrFlag: dc.w 0 ;Flag for Errors
;Verify-Bit = 1 => Error
TNumBufferA: dc.w 0 ;Track-Number memory
;for 1D-Copy (Start-Track)
TNumBufferE dc.w 0 ;Buffer for End number
;of loaded Tracks
BlockMessage: ds.w 11
;Cruncher
Length: dc.w $1600
ShrtByte: dc.b 0
align.w
TrackPointer: ds.l 164 ;memory for Pointer to packed Tracks
MemoryBeg: dc.l 0 ;memory beginning for crunching
MemoryLength: dc.l 0 ;memory length for Crunching
MemoryChip: dc.l 0
LengthChip: dc.l 0
FreeFlagCh: dc.w 0
MemoryFast: dc.l 0
LenghtFast: dc.l 0
FreeFlagFa: dc.w 0
Subtr: dc.w 0 ;See CrunEnd2
;Control
TrackBuffer1: dc.l 0
TrackBuffer2: dc.l 0
TrackNumS: dc.w 0
TrackNumD: dc.w 0
TrackNum: dc.w 0
StartTrack: dc.w 0 ;first Track to be read
EndTrack dc.w 0 ;last Track to be read
MotorBits: dc.b $F3
MotorBitsS: dc.b $F3
MotorBitsD: dc.b $F3
Flag: dc.b $00 ;indicates if Source or Dest.
align.w
;Deep Copy
Position: dc.l 0 ;For Search routine
BitShifts: dc.w 0 ;number of Bits during shift
Size1: dc.w 0 ;size of the largest Block
Size2: dc.w 0 ;size of the second largest Block
SizePos: dc.l 0 ;Position of the largest Block
Searchln: dc.w 0 ;how many defective Words can there be
NumWords: dc.w 0 ;how many Words are compared
ErrorFlag: dc.w 0
EndPos: dc.l 0 ;End position of Track
BegPos: dc.l 0 ;beginning of Track (after Gap)
SLength: dc.w 0 ;number of Bytes to be written
WriteAddrs: dc.l 0 ;Address from which writing starts
Offset: dc.w 0 ;number of Bytes before Sync during writing
TrackBytes: dc.w 0 ;Bytes on the Track
CheckLength: dc.w 0 ;Bytes on the Track (Controll)
LenghtDest: dc.w 0 ;Track length of Dest.-Disk
Syncwidth: dc.w 0 ;Distance from Index to Sync
SyncNum: dc.w 0 ;number of Syncs found
CopyTry1: dc.w 0 ;Illegal Data, read how many times
CopyTry2: dc.w 0 ;how many times read for NoSync
Blocks: ds.l SortBlockNum ;memory for Blocklength+SyncNum
SortBlocks: ds.l SortBlockNum ;memory for Block sorting
NumSortBlock: dc.w 0 ;number of different sorted Blocks
SyncWord: dc.w $4489 ;Value for reading
;Table for Sync-Search
;Sync = $4489
SyncBase: dc.l %01000100100010010000000000000000
dc.l %00100010010001001000000000000000
dc.l %00010001001000100100000000000000
dc.l %00001000100100010010000000000000
dc.l %00000100010010001001000000000000
dc.l %00000010001001000100100000000000
dc.l %00000001000100100010010000000000
dc.l %00000000100010010001001000000000
dc.l %00000000010001001000100100000000
dc.l %00000000001000100100010010000000
dc.l %00000000000100010010001001000000
dc.l %00000000000010001001000100100000
dc.l %00000000000001000100100010010000
dc.l %00000000000000100010010001001000
dc.l %00000000000000010001001000100100
dc.l %00000000000000001000100100010010
dc.l %00000000000000000100010010001001
AmigaTrack: dc.b 0 ;indicates if Amiga-Format on DeepCopy
fc: dc.b 00 ;First Cylinder
lc: dc.b 79 ;Last "
tr: dc.b 3 ;Tries
ws: dc.b 0 ;Write repeatedly
vd: dc.b 1 ;Verify
fa: dc.b 1 ;Fast Copy
dc1: dc.b 0 ;D1 Copy
dc2: dc.b 0 ;D2 Copy
sd: dc.b 1 ;SourceBits
dd: dc.b 2 ;DestDits
sy: dc.b 0 ;Sync correction
waiting: dc.b 0 ;irq wait_conter
DevName: dc.b "trackdisk.device",0
END